Synchronise a props in Vuejs

2019-06-01 01:54发布

I'm trying to synchronize a prop between a parent and child in .

I have a parent component that includes a child component with a prop. When the prop changes in the parent, the prop is updated in the child and when the prop changes in the child, the parent is updated.

I started with this example:

The html where my component is mounted

<div>
   <div id="app">
   </div>
</div>

And the parent + child:

Vue.component('myinput', {
   template: '<div><input v-model="mytext" /></div>',
   props: ['text'],

   data() {
      return {
         mytext: this.text
      }
   }
})

const vm = new Vue({
   el: '#app',
   template: '<div> <myinput :text="mytext"></myinput> <p> {{mytext}} </p></div>',

   data() {
      return {
         mytext: "Hello World!"
      }
   }
});

Since I cannot mutate the props, I need a local copy [Example Codepen].

If I want my parent component to be updated when the child change, I need to $emit the value.

For that, I created a wrapper around mytext in the child component:

computed: {
     wrapperMyText: {
       get() {
         return this.mytext;
       },
       set(v) {
         this.mytext = v;
         this.$emit('update:text', v);
       }
     }

I use wrapperMyText in the model. [Example Codepen]

Now, if I want the binding the other way (parent to child) I need to add a watcher in the child.

watch: {
     text(v) {
       this.mytext = v;
     }
   },

[Example Codepen].

In the example, there is only one prop, I need to create a watcher and a computed property. If I have 5 properties, I will need 5 watchers and 5 computed properties. That means the component code is polluted (too much code) with all this stuff. So my questions are:

Is this the standard pattern to sync a prop?
Is it better in this case to use a Store (like vuex)?
Why is so much code necessary to do a simple case?

After reflection, it seems I'm trying to re code v-model with properties.

1条回答
我命由我不由天
2楼-- · 2019-06-01 02:37

A single computed property will accomplish everything you are attempting.

Vue.component('myinput', {
   template: '<div><input v-model="wrapperMyText"></div>',
   props: ['text'],
   computed: {
     wrapperMyText: {
       get() { return this.text;},
       set(v) { this.$emit('update:text', v);}
     }
   }
})

Here is your updated pen.

So to answer your questions:

  1. This is a standard pattern.
  2. If you put the state in Vuex, your input component will no longer be re-usable.
  3. You don't need all that code.
查看更多
登录 后发表回答