如何监听“props”变化

IT技术 javascript vue.js vuejs2 vue-component
2021-03-04 03:51:11

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

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

更新

正如@wostex 建议的那样,我尝试使用watch我的财产,但没有任何改变。然后我意识到我有一个特殊情况:

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

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

myProp将父组件接收到的信息传递child组件。然后watch: {myProp: ...}不工作。

6个回答

你可以通过watchprops 在 props 改变时执行一些代码:

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>

@SethWhite 根据我对使用观察者模式在 Vue 中处理反应性的理解,观察者不一定比计算数据或其他反应性数据效率低。在属性值取决于许多值的情况下,计算的 prop 将运行单个函数,而不是为结果所依赖的每个值运行单独的 watch 回调。我认为在最常见的用例中,计算属性会产生所需的结果。
2021-04-18 03:51:11
我在看道具时在手表部分看到一个没有键的符号。只有一个功能。是否有关于此符号的任何文档(vue 2)?
2021-04-27 03:51:11
如果道具发生变化而不是使用观察者,那么使用道具的东西不应该重新渲染吗?
2021-05-03 03:51:11
对于希望使用类(例如在typescript中)执行此操作的任何人,请查看此答案
2021-05-08 03:51:11
我知道 watch 是不鼓励的,因为使用计算属性通常更好,但是使用 watch 有任何性能问题吗?
2021-05-12 03:51:11

你试过这个吗?

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

这对我有用,但如果有解释它为什么起作用的解释会很有帮助。
2021-05-10 03:51:11

在我的情况下,我需要一个解决方案,任何时候任何props都会改变,我需要再次解析我的数据。我厌倦了为所有props制作单独的观察者,所以我使用了这个:

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

从这个例子中拿走的关键点是使用deep: trueso 它不仅可以监视$props而且还可以嵌套值,例如props.myProp

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

谢谢,我想现在我们可以点赞了。或者OP可以改变它
2021-04-23 03:51:11
这应该被标记为答案,因为它是将深度对象观察设置为观察者对其属性更改的适当方法。
2021-05-05 03:51:11

您需要了解您所拥有的组件层次结构以及您如何传递props,当然您的情况很特殊,开发人员通常不会遇到。

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

如果 myProp 在父组件中更改,它也会反映在子组件中。

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

因此,如果 myProp 在父组件中更改,那么它将反映在孙组件中。(到目前为止,一切都很好)。

因此,在层次结构中,您不必做任何事情props将具有内在的react性。

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

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

如果 myProp 在子组件中更改,则不会反映在父组件中。您必须在父组件中使用 .sync 修饰符并从子组件发出事件。

如果在grandChild 组件中更改了myProp,它将不会反映在父组件中(显然)。您必须使用 .sync 修饰符 child 并从孙组件发出事件,然后观察子组件中的 prop 并在父组件使用 .sync 修饰符侦听的更改时发出事件。

让我们看一些代码以避免混淆

父.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>

儿童.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>

孙子.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>

但是在此之后,您将无法帮助注意到 vue 说的尖叫警告

“避免直接改变 prop,因为每当父组件重新渲染时,该值都会被覆盖。”

同样,正如我之前提到的,大多数开发人员都不会遇到这个问题,因为这是一种反模式。这就是您收到此警告的原因。

但是为了解决您的问题(根据您的设计)。我相信你必须做上述工作(老实说是黑客)。我仍然建议您重新考虑您的设计,并且 make 不太容易出现错误。

我希望它有帮助。

不确定你是否已经解决了(如果我理解正确),但这是我的想法:

如果 parent 收到 myProp,并且您希望它传递给 child 并在 child 中观看它,则 parent 必须拥有 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>

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