VueJs 2.0 - 如何监听`props`的变化

Ami*_*.io 190 javascript vue.js vue-component vuejs2

VueJs 2.0文档中,我找不到任何可以监听props变化的钩子.

VueJs有类似onPropsUpdated()或类似的钩子吗?

更新

正如@wostex建议的那样,我尝试了watch我的财产但没有改变.然后我意识到我有一个特例:

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

<script>
   export default {
      props: ['myProp']
   }
</script>
Run Code Online (Sandbox Code Playgroud)

我传递的myProp是父组件接收到child组件.那watch: {myProp: ...}就是不行.

Ego*_*kio 241

你可以使用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)
        }
      }
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 如果道具发生变化而不是使用观察者,那么使用道具的东西不应该重新渲染吗? (3认同)

小智 54

你试过这个吗?

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

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

  • 这对我有用,但如果能解释它为什么有效,那将会很有帮助。 (7认同)
  • 这对我有用,答案没有 - 也许这是一个更新.谢谢BearInBox :) (6认同)

Joe*_*chr 14

他,

就我而言,我需要一个解决方案,只要任何道具都会发生变化,就需要再次解析我的数据。我已经厌倦了为所有道具制作单独的观察器,所以我使用了以下方法:

  watch: {
    $props: {
      handler() {
        this.parseData();
      },
      deep: true,
      immediate: true,
    },
Run Code Online (Sandbox Code Playgroud)

该示例的重点是使用,deep: true因此它不仅监视$ props,而且还嵌套了诸如eg的值props.myProp

您可以在此处了解有关此扩展监视选项的更多信息:https : //vuejs.org/v2/api/#vm-watch


The*_*Man 7

您需要了解,您正在拥有的组件层次结构以及如何传递道具,绝对是您的情况特殊而且通常不会遇到开发人员.

父组件-myProp->子组件-myProp->孙组件

如果在父组件中更改了myProp,它也将反映在子组件中.

如果在子组件中更改myProp,它也将反映在孙组件中.

因此,如果在父组件中更改了myProp,那么它将反映在孙组件中.(到现在为止还挺好).

因此,在层次结构中,您不必做任何道具将具有固有的反应性.

现在谈论在层次结构中上升

如果在grandChild组件中更改myProp,它将不会反映在子组件中.您必须在child中使用.sync修饰符并从grandChild组件中使用emit事件.

如果在子组件中更改了myProp,它将不会反映在父组件中.您必须在父级中使用.sync修饰符,并从子组件中使用emit事件.

如果在grandChild组件中更改myProp,它将不会反映在父组件中(显然).您必须使用.sync修饰符子项并从孙组件中发出事件,然后在子组件中观察prop,并使用.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>
Run Code Online (Sandbox Code Playgroud)

Child.vue

<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>
Run Code Online (Sandbox Code Playgroud)

Grandchild.vue

<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>
Run Code Online (Sandbox Code Playgroud)

但在此之后,你不会注意到vue说的尖叫警告

'避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖.

正如我之前提到的,大多数开发人员都没有遇到过这个问题,因为它是一种反模式.这就是你得到这个警告的原因.

但是为了解决你的问题(根据你的设计).我相信你必须做上述工作(说实话).我仍然建议您重新考虑您的设计并使其不易出错.

我希望它有所帮助.


m.c*_*acz 6

不知道您是否已解决它(以及我是否理解正确),但这是我的想法:

如果父级收到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 }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

并在html中:

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 }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

实际上,在这种情况下处理复杂的集合(传递几次)时,您必须非常小心


Md *_*san 6

对于双向绑定,您必须使用 .sync 修饰符

<child :myprop.sync="text"></child>
Run Code Online (Sandbox Code Playgroud)

更多细节...

并且您必须在子组件中使用 watch 属性来监听和更新任何更改

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


Wou*_*ofs 6

我使用计算属性,例如:

    items:{
        get(){
            return this.resources;
        },
        set(v){
            this.$emit("update:resources", v)
        }
    },
Run Code Online (Sandbox Code Playgroud)

在这种情况下,资源是一个属性:

props: [ 'resources' ]
Run Code Online (Sandbox Code Playgroud)