在VueJs 2.0文档中,我找不到任何可以监听道具变化的钩子。

VueJs有这样的钩子像onpropsupdate()或类似的吗?

更新

正如@wostex建议的那样,我试着观察我的财产,但没有任何变化。然后我意识到我遇到了一个特殊的情况:

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

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

我将父组件接收到的myProp传递给子组件。然后手表:{myProp:…不起作用。


当前回答

你需要理解,你拥有的组件层次结构和你如何传递道具,你的情况肯定是特殊的,通常不会被开发人员遇到。

父组件- myprop ->子组件- myprop ->孙子 组件

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

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

因此,如果myProp在父组件中被更改,那么它将反映在孙辈组件中。(到目前为止还不错)。

因此,在层次结构中,你不需要做任何事情,道具将具有固有的反应性。

现在说到等级的上升

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

如果myProp在子组件中被更改,它将不会反映在父组件中。你必须在父组件中使用.sync修饰符,并从子组件中触发事件。

如果myProp在grandChild组件中被更改,它将不会反映在父组件中(显然)。你必须使用.sync修饰符子组件并从孙子组件发出事件,然后观察子组件中的道具并在更改时发出事件,该事件由使用.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>

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>

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>

但在这之后,你会情不自禁地注意到vue说的尖叫警告

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

正如我之前提到的,大多数开发者不会遇到这个问题,因为这是一个反模式。这就是为什么你会得到这个警告。

但是为了解决你的问题(根据你的设计)。我相信你已经做了上面的工作(诚实地说,黑客)。我仍然建议你应该重新考虑你的设计,让它更不容易出现bug。

我希望这能有所帮助。

其他回答

我认为在大多数情况下,Vue会在道具变化时更新组件的DOM。

如果这是你的情况,那么你可以使用beforeUpdate()或updated()钩子(docs)来观察道具。

如果你只对新val感兴趣而不需要旧val,你可以这样做

new Vue({ el: '#app', data: { text: '' }, components: { 'child': { template: `<p>{{ myprop }}</p>`, props: ['myprop'], beforeUpdate() { console.log(this.myprop) }, updated() { console.log(this.myprop) } } } }); <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <child :myprop="text"></child> <input v-model="text" placeholder="Type here to view prop changes" style="width:20em"> </div>

你试过这个吗?

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

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

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

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

从这个例子中得到的关键点是使用deep: true,这样它不仅监视$props,而且还监视它的嵌套值,例如props. myprop

你可以在这里了解更多关于这款扩展手表的选择:https://v2.vuejs.org/v2/api/#vm-watch

道具和v型模型处理。如何将值从父对象传递给子对象,再从子对象传递给父对象。

不需要手表!另外,在Vue中改变道具也是一种反模式,所以永远不要改变子组件或组件中的道具值。使用$emit更改值,Vue将始终按预期工作。

/* COMPONENT - CHILD */ Vue.component('props-change-component', { props: ['value', 'atext', 'anumber'], mounted() { var _this = this this.$emit("update:anumber", 6) setTimeout(function () { // Update the parent binded variable to 'atext' _this.$emit("update:atext", "4s delay update from child!!") }, 4000) setTimeout(function () { // Update the parent binded v-model value _this.$emit("input", "6s delay update v-model value from child!!") }, 6000) }, template: '<div> \ v-model value: {{ value }} <br> \ atext: {{ atext }} <br> \ anumber: {{ anumber }} <br> \ </div>' }) /* MAIN - PARENT */ const app = new Vue({ el: '#app', data() { return { myvalue: 7, mynumber: 99, mytext: "My own text", } }, mounted() { var _this = this // Update our variable directly setTimeout(function () { _this.mytext = "2s delay update mytext from parent!!" }, 2000) }, }) <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <props-change-component v-model='myvalue' :atext.sync='mytext' :anumber.sync='mynumber'> </props-change-component> </div>

你可以观察道具,在道具改变时执行一些代码:

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>