1. The props and $emit


The parent component passes data to the child component via prop, and the child component passes data to the parent via a $emit trigger event

  Vue.component( "child", { 
                    data () { return {  mymessage:this.message  }  },
                    template:`<div><input type="text" v-model="mymessage" @input="setFather(mymessage)"></div> `,
                    props:{message:String},
                    methods:{setFather (val){this.$emit("getChildData",val) }  }})   
  Vue.component("parent",{ 
                     data:function () { 
                        return {messageFather:"Son, I'm your father."} }, template:` <div> <p> this is parentcomponent! </p><child :message="messageFather" @getChildData="getChildData"></child>  </div> `,   
                       methods:{ getChildData(val){ console.log(val) } } }) 
                       var app = new  Vue({   el:"#app",})Copy the code

2. $attrs and $listeners

The first way to handle data transfers between parent and child components presents A problem: If parent component A has child component B under it, and component B has component C under it, what if component A wants to pass data to component C? If we take the first approach, we have to have component A pass messages through prop to component B, and component B pass messages through Prop to component C; If there are more components between components A and C, this approach becomes complicated. Vue 2.4 started with $listeners and $attrs to fix this problem, allowing messages to be sent from component A to component C

  <script>    Vue.component("childs", {data() {        return{          mymessages:"I might have to hear from my grandfather."}}, template: '<div> <p> I am the son of the son </p> <inputtype="text" v-model="$attrs.messageChilds" @input="getGrandChild($attrs.messageChilds)">          </div>      `,      methods:{        getGrandChild(val){          this.$emit("getGrandChild",val)        }      }    })    Vue.component("child", {data () {        return {          mymessage:this.message        }      },      template:`        <div>            <input type="text" v-model="mymessage" @input="setFather(mymessage)">              <childs  v-bind="$attrs" v-on="$listeners"></childs>        </div>      `,      props:{        message:String      },      methods:{        setFather (val){          this.$emit("getChildData",val)        }      }    })    Vue.component("parent",{      data:function () {        return {          messageFather:"Son, I'm your father.",          messageGrandFather:"Son, I'm your father."} }, template:` <div> <p> this is parentcomponent! </p> <child :messageChilds="messageGrandFather" :message="messageFather" @getChildData="getChildData" @getGrandChild="getGrandChild"></child>        </div>      `,      methods:{        getChildData(val){          console.log(val)        },        getGrandChild(val){          console.log(val)        }      }    })    var app = new  Vue({      el:"#app",    })  </script>Copy the code

<script> 
   Vue.component("childs", {data() { return{ mymessages:"I might have to hear from my grandfather."}}, template: '<div> <p> I am the son of the son </p> <inputtype="text" v-model="$attrs.messageChilds" @input="getGrandChild($attrs.messageChilds)"> </div>  `,    
      methods:{  getGrandChild(val){ this.$emit("getGrandChild",val)} } }) 
   Vue.component("child", {data () {
        return {
           mymessage:this.message  
           }    
        },    
           
      template:` <div> <input type="text" v-model="mymessage" @input="setFather(mymessage)">  <childs  v-bind="$attrs" v-on="$listeners"></childs> </div>    `,     
       props:{ message:String  },     
       methods:{ setFather (val){this.$emit("getChildData",val) }  } })  
       Vue.component("parent",{ 
         data:function () {  
          return {  
             messageFather:"Son, I'm your father.", 
             messageGrandFather:"Son, I'm your father."} }, template:` <div> <p> this is parentcomponent! </p> <child :messageChilds="messageGrandFather" :message="messageFather" @getChildData="getChildData" @getGrandChild="getGrandChild">
                      </child>        </div>      `,      
          methods:{   
            getChildData(val){ 
              console.log(val)   
               },       
             getGrandChild(val){ 
               console.log(val)     
              }   
               
             }   
               
            })  
         var app = new  Vue({      el:"#app",    })  </script>Copy the code

This method is done by binding v-bind=”$attrs” to v-listeners by thinking of the target’s child components; $attrs. MessageChild ($attrs. MessageChild, $attrs. MessageChild, $attrs. MessageChild, $attrs. MessageChild, $attrs. MessageChild, $attrs.

3. Central event bus

Both approaches deal with data passing between parent and child components, but what if the two components are not parent and child? A central event bus can be used in this case. Create a new Vue event bus object and emit events via bus.$ON.

  <script>    Vue.component("brotherb", {data () {        return {          mymessageBrotherB:"I am brotherb",          brothera:' '        }      },      template:`        <div>          <p>{{mymessageBrotherB}}</p>          <p>{{brothera}}</p>        </div>      `,      props:{        message:String,            },      mounted(){        bus.$on('globalEvent',(val)=>{         this.brothera=val       })      }    })    Vue.component("brothera",{      data:function () {        return {          messageBrotherA:"I am brotherA",          mymessage:"Hello, brotherB"        }      },      template:`        <div>          <p>{{messageBrotherA}}</p>           <input type="text" v-model="mymessage" @input="passData(mymessage)">        </div>      `,      methods:{        passData(val){          bus.$emit("globalEvent",val)}}}) // Const bus=new Vue(); const app = new Vue({ el:"#app",    })  </script>Copy the code

The parent of the mthods component passes event handlers via bus.$emit(), and the sibling of the mounted hook function receives events and methods via bus.$on().

4. Dojo.provide and inject

Variables are provided by providers in the parent component and injected by inject in the child component. No matter how deep the child component is, as long as inject is invoked, the data in the provider can be injected. Rather than being limited to fetching data only from the prop property of the current parent component, child components can be called as long as the parent component lives.

<script>    Vue.component("child",{      inject:['for'].data () {        return {          mymessage:"I am the son.",          messageFather:this.for        }      },      template:`        <div>          <p>{{mymessage}}</p>          {{messageFather}}        </div>      `,      mounted(){      }    })    Vue.component("parent",{      data:function () {        return {          mymessage:"I am the father"        }      },      provide:{        for:"Hello, son."      },      template:`        <div>          <p>{{mymessage}}</p>           <child></child>        </div>      `,      methods:{             }    })    const app = new Vue({      el:"#app",    })  </script>Copy the code

5. v-model

When the parent component passes a value to the child component via the V-model, a prop property of value is automatically passed, and the value of the V-model binding is automatically modified in the child component via this.$emit(‘ input’,val)

  Vue.component("child",{      props:{        value:String      },      data () {        return {          mymessage:this.value,        }      },      template:`        <div>          <input  type="text" v-model="mymessage" @change="changeValue">        </div>      `,      mounted(){      },      methods:{        changeValue() {          this.$emit('input',this.mymessage)        }      }    })    Vue.component("parent",{      data:function () {        return {          message:"son",        }      },      template:`        <div>          <p>{{message}}</p>           <child v-model="message"></child>        </div>      `,      methods:{             }    })    const app = new Vue({      el:"#app",    })  </script>Copy the code

6. $the parent and children

 <script>    Vue.component("child", {data () {        return {          mymessage:"I am the son.",        }      },      template:`        <div>         <input type="text" v-model="mymessage" @change="changeParent">        </div>      `,      mounted(){      },      methods:{        changeParent () {          this.$parent.message=this.mymessage        }      }    })    Vue.component("parent",{      data:function () {        return {          message:"I am the father",        }      },      template:`        <div>          <p>{{message}}</p>           <button @click="changeBtn"Child > > change son < / button > < < / child > < / div > `, the methods: {changeBtn () {          this.$children[0].mymessage="hello"        }      }    })    const app = new Vue({      el:"#app",    })  </script>Copy the code

$this.$children[1]. Message =”hello”

The child modifies the value of message in the parent by calling this.$parent. Message =this. myMessage.

7. Vuex handles data interaction between components

If the business logic is complex, many components need to handle some public data at the same time, this time is that some methods may be bad for maintenance of the project, the practice of vuex is the abstract some public data, and then other components can read and write operations to the public data, so that achieve the goal of decoupling.