Vue propsData not updating dynamically

2019-07-27 04:08发布

问题:

I've been struggling with this issue for hours: I've instantiated dynamically a child vue component inside a parent component, and passed in propsData some of the parent's data. The dynamically created child's properties doesn't seem to update when the parent updates.

Please check the example I created for a better understanding (forked from chinchang's example)

As you can see, I'm instantiating Button components both dynamically and statically. The color of the button depends on the type property. I pass the parent's data(the type attribute) as props both to the dynamically and statically created instances. When you insert a new button, by clicking the 'Click to insert' button, a new Button is created, using the parent's current type. After the click event, I switch the parent's type attribute. As you can see the statically created button instance (on the top on the page) changes color, but the dynamically instantiated ones remain the same.

Could you point out my mistake please and help to find a solution?

Thanks, Ábel

回答1:

From the docs:

Pass props to an instance during its creation. This is primarily intended to make unit testing easier.

Setting propsData does not create a parent-child relationship. It simply provides (non-reactive) data to the component. In short, you've chosen a not-very-Vue approach. You shouldn't be concerned with creating components, you should have data items in your viewmodel that Vue then creates components for.

  export default {
    name: 'app',
    components: { Button },
    data(){
      return {
        type: 'secondary',
        buttons: []
      };
    },
    methods: {
      onClick() {
        this.buttons.push(true);
        if(this.type === 'primary'){
          this.type = 'secondary';
        } else {
          this.type = 'primary';
        }
      }
    }
  }

and

  <div ref="container">
    <button @click="onClick">Click to insert</button>
    <Button v-for="b in buttons" :type="type">Click me!</Button>
  </div>

Fixed demo