2

I've seen some questions about vue.js watchers, but i didnt find a question handling my problem, so here it is:

In my SomeComponent.vue i use this code:

...
props: ['value']
,
watch: {
    value(val) {
        console.log(val);
    }
},

In my parent vue page, that uses this component i use this, which is working:

<template>
    <div>
        <SomeComponent
            v-model="test"
        ></SomeComponent>
    </div>
</template>
data() {
    return {
        test: {}
    };
},
created() {
    this.test = this.DoSomething();
},

If i add another property the watcher is not triggered anymore:

<template>
    <div>
        <SomeComponent
            v-model="test"
        ></SomeComponent>
    </div>
</template>
data() {
    return {
        test: {}
    };
},
created() {
    this.test.Prop1 = this.DoSomething();
    this.test.Prop2 = "Test";
},

EDIT: After Behappy's Answer my Component Part looks like this now:

...
props: ["value"],
watch: {
    value: {
        handler(val) {
            console.log(val);
        },
        deep: true
    }
},

2 Answers 2

4

This is because your prop is an Object.

For deeply watching you can do this:

watch: {
    value: {
        handler(val) {
          console.log(val);
        },
        deep: true
    }
},

and in created DOM is not rendered yet. So prop you sent to child component is not updated yet.refer link

and as in other answers the correct way to change Object is to use this.$set:

  mounted() {
    this.$set(this.test, 'Prop1', this.DoSomething())
    this.$set(this.test, 'Prop2', 'Test')
  },
Sign up to request clarification or add additional context in comments.

1 Comment

your welcome. and I think changing in created won't trigger watch, because value changes before sending to child component.
3

As mentioned in the docs:

Due to limitations in JavaScript, there are types of changes that Vue cannot detect. However, there are ways to circumvent them to preserve reactivity.

For Objects

Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive. For example:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` is now reactive

vm.b = 2
// `vm.b` is NOT reactive

Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the this.$set(object, propertyName, value) method:

In your case that would be:

created() {
    this.$set(this.test, 'Prop1', this.DoSomething())
    this.$set(this.test, 'Prop2', "Test")
},

Or, you can also assign a number of properties to an existing object, for example, using Object.assign() like:

this.test = Object.assign({}, this.test, { 'Prop1': 1, 'Prop2': 2 })

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.