web-dev-qa-db-ja.com

VueJs 2.0 - 「小道具」の変更を監視する方法

VueJs 2.0のドキュメントにpropsの変更を監視するフックが見つかりません。

VueJはonPropsUpdated()のようなフックを持っていますか?

更新

@wostexが示唆したように、私は自分の財産をwatchしようとしましたが、何も変わりませんでした。それから私は私が特別なケースを持っていることに気づいた:

<template>
    <child :my-prop="myProp"></child>
</template>

<script>
   export default {
      props: ['myProp']
   }
</script>

親コンポーネントが受け取るmyPropchildコンポーネントに渡します。それならwatch: {myProp: ...}は機能していません。

121
Amio.io

あなたは小道具の変更時にいくつかのコードを実行するためにwatch小道具を使うことができます:

new Vue({
  el: '#app',
  data: {
    text: 'Hello'
  },
  components: {
    'child' : {
      template: `<p>{{ myprop }}</p>`,
      props: ['myprop'],
      watch: { 
        myprop: function(newVal, oldVal) { // watch it
          console.log('Prop changed: ', newVal, ' | was: ', oldVal)
        }
      }
    }
  }
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <child :myprop="text"></child>
  <button @click="text = 'Another text'">Change text</button>
</div>
157
Egor Stambakio

これを試しましたか?

watch: {
  myProp: {
    // the callback will be called immediately after the start of the observation
    immediate: true, 
    handler (val, oldVal) {
      // do your stuff
    }
  }
}

https://vuejs.org/v2/api/#watch

38
BearInBox

あなたが理解している必要があります、あなたが持っているコンポーネント階層とあなたが小道具をどのように渡しているか、確かにあなたのケースは特別で、通常開発者によって遭遇されません。

親コンポーネント-myProp->子コンポーネント-myProp->孫コンポーネント

MyPropが親コンポーネントで変更された場合、 は子コンポーネントにも反映されます

そして、myPropが子コンポーネントで変更された場合、 は孫コンポーネントにも反映されます

そのため、myPropが親コンポーネントで変更された場合、 は孫コンポーネントに反映されます 。 (ここまでは順調ですね)。

したがって、階層の下では、何もする必要はありません。小道具は本質的に反応的です。

今階層で上がることについて話している

MyCropがgrandChildコンポーネントで変更された場合、 は子コンポーネントに反映されません 。あなたは子で.sync修飾子を使用して、grandChildコンポーネントからイベントを発行する必要があります。

MyPropが子コンポーネントで変更された場合、 は親コンポーネントには反映されません 。親で.sync修飾子を使用し、子コンポーネントからイベントを発行する必要があります。

MyPropがgrandChildコンポーネントで変更された場合、 は親コンポーネントには反映されません (明らかに)。あなたは、.sync修飾子childを使用して、孫コンポーネントからイベントを発行し、それから子コンポーネントで小道具を監視し、.sync修飾子を使用して親コンポーネントによって監視されているイベントを変更する必要があります。

混乱を避けるためにいくつかのコードを見てみましょう

Parent.vue

<template>
    <div>
    <child :myProp.sync="myProp"></child>
    <input v-model="myProp"/>
    <p>{{myProp}}</p>
</div>
</template>

<script>

    import child from './Child.vue'

    export default{
        data(){
            return{
                myProp:"hello"
            }
        },
        components:{
            child
        }
    }
</script>

<style scoped>
</style>

こども

<template>
<div>   <grand-child :myProp.sync="myProp"></grand-child>
    <p>{{myProp}}</p>
</div>

</template>

<script>
    import grandChild from './Grandchild.vue'

    export default{
        components:{
            grandChild
        },
        props:['myProp'],
        watch:{
            'myProp'(){
                this.$emit('update:myProp',this.myProp)

            }
        }
    }
</script>

<style>

</style>

お孫さん

<template>
    <div><p>{{myProp}}</p>
    <input v-model="myProp" @input="changed"/>
    </div>
</template>

<script>
    export default{
        props:['myProp'],
        methods:{
            changed(event){
                this.$emit('update:myProp',this.myProp)
            }
        }
    }
</script>

<style>

</style>

しかし、この後あなたはvueの叫び声が叫んでいるという警告に気づかないでいる

「親コンポーネントが再レンダリングされるたびに値が上書きされるため、プロップを直接変更しないでください。」

前述したように、これはアンチパターンであるため、ほとんどの開発者はこの問題に遭遇しません。だからあなたはこの警告を受けます。

しかしあなたの問題を解決するために(あなたの設計に従って)。私はあなたが上記の回避策をしなければならないと信じる(正直に言うとハック)。私はまだあなたがあなたのデザインを再考するべきであることをお勧めし、makeはバグを起こしにくいです。

助けになれば幸いです。

5

あなたがそれを解決したかどうか(そして私が正しく理解したかどうか)はわからないが、ここに私の考えがある:

親がmyPropを受け取り、それを子に渡して子で監視する場合は、親はmyPropのコピーを持っている必要があります(参照ではありません)。

これを試して:

new Vue({
  el: '#app',
  data: {
    text: 'Hello'
  },
  components: {
    'parent': {
      props: ['myProp'],
      computed: {
        myInnerProp() { return myProp.clone(); } //eg. myProp.slice() for array
      }
    },
    'child': {
      props: ['myProp'],
      watch: {
        myProp(val, oldval) { now val will differ from oldval }
      }
    }
  }
}

そしてhtmlで:

<child :my-prop="myInnerProp"></child>

そのような状況で複雑なコレクションを扱うときには、実際には非常に注意を払う必要があります(数回過ぎる)

5
m.cichacz

彼、

私の場合は、小道具が変わるたびにデータを解析する必要があるソリューションが必要でした。私はすべての私の小道具のために別々のウォッチャーを作るのにうんざりしていたので、私はこれを使いました:

  watch: {
    $props: {
      handler() {
        this.parseData();
      },
      deep: true,
      immediate: true,
    },

この例から抜け出すための重要なポイントはdeep: trueを使うことです。それはそれが$ propsを見るだけでなくそれがネストされた値のようなものでもあります。 props.myProp

あなたはここでこの拡張された監視オプションについてもっと学ぶことができます: https://vuejs.org/v2/api/#vm-watch

3
JoeSchr

双方向バインディングの場合は、.sync修飾子を使用する必要があります。

<child :myprop.sync="text"></child>

詳細...

そして、あなたは子コンポーネントのwatchプロパティを使って変更を監視し更新する必要があります。

props: ['myprop'],
  watch: { 
    myprop: function(newVal, oldVal) { // watch it
      console.log('Prop changed: ', newVal, ' | was: ', oldVal)
    }
  }
2

私は次のように計算されたプロパティを扱います。

    items:{
        get(){
            return this.resources;
        },
        set(v){
            this.$emit("update:resources", v)
        }
    },

この場合、リソースはプロパティです。

props: [ 'resources' ]
2
Wouter Schoofs

監視モードを使用して、変更を検出できます。

原子レベルですべてを行います。そのため、最初にwatchメソッド自体が呼び出されているかどうかを確認するために、内部の何かを慰めます。時計が呼び出されることが確立されたら、ビジネスロジックで時計を破壊します。

watch: { 
  myProp: function() {
   console.log('Prop changed')
  }
}
0
Rahul Sharma