8 ways of Vue component communication

Posted by pessi on Tue, 15 Feb 2022 05:43:08 +0100

preface

The company's system, which has been done for half a year, is finally online the day before yesterday. It took too long to change the BUG in the later stage. Most of the bugs were caused by the asymmetric information between the front-end and the back-end. There were few logical errors and the user experience was a little poor. After all, it was the first time to build such a large system (100w +). Through this system development, I summarized a lot of experience on how to better cooperate with the back-end personnel in development and how to design to improve the user experience, Before doing their own development, they didn't pay attention to this aspect, only pay attention to the function realization, and make up more in the later stage. After the project goes online, the next step is the maintenance and update in the later stage. Recently, it is not as busy as before, and the system is simply restored. As the technical stack used in the project is Vue, the usual development only focuses on the function realization. Next, Vue will be deeply analyzed to encapsulate common business components and Vue source code analysis This chapter will summarize the 8 methods of Vue component communication. The daily development of component communication is close. Being familiar with component communication can better develop business.

Value transfer between Vue components

1. Pass values from parent component to child component

Introducing child components into parent components Register subcomponents Use in the page, and dynamically bind the incoming dynamic value / static value on the sub component label In the child component, props is used to accept the value passed by the parent component

The value of the parent component received by the child component can be divided into reference type and normal type:

Common types: String, Number, Boolean, Null Reference type: Array, Object

#Parent component

<template>
  <div>
    <!-- Transfer value -->
    <Test
     :obj="obj" 
     info="test"/>
  </div>
</template>

<script>
// Introducing sub components
import Test from "../components/Test.vue";
export default {
  name: "about",
  // Register subcomponents
  components: {
    Test,
  },
  data() {
    return {
      obj: {
        code: 200,
        title: "Front end self-study community",
      },
    };
  },
};
</script>
<template>
    <div>
        <h1>{{obj.code}}</h1><br>
        <h2>{{obj.title}}</h2>
        <h3>{{info}}</h3>
    </div>
</template>

<script>
    export default {
        name:'test',
        props:{
            obj:Object,
            info: [String,Number]  //info value can be one of these types, and other types of alarms
        }
    }
</script>

Because Vue is a one-way data flow, the child component cannot directly modify the value of the parent component.

2. The child component passes the value to the parent component

Subcomponents bind events through this$ Emit ('function name ', pass parameter)

#Parent component

<Test
     :obj="obj" 
     info="test"
     @modify="modifyFatherValue"/>

<script>
// Introducing sub components
import Test from "../components/Test.vue";
export default {
  name: "about",
  // Register subcomponents
  components: {
    Test,
  },
  data() {
    return {
      msg:'I am the parent component'
    };
  },
  methods:{
    // Accept the value passed by the subcomponent and assign it to the attribute in data
    modifyFatherValue(e){
      this.msg = e
    }
  }
};
</script>
# Subcomponents

<button @click="modifyValue">Modify the value of the parent component</button>


<script>
    export default {
        name:'test',
        methods:{
            modifyValue(){
                this.$emit('modify','The value passed by the subcomponent')
            }
        }
    }
</script>

3. The parent component obtains the value of the child component through $refs / $children

$refs :

Get DOM elements and component instances to get the properties and methods of components. By binding ref on the subcomponent, use this$ refs. refName. Subcomponent properties / subcomponent methods

$children :

The subcomponent of the current instance, which returns a collection of subcomponents. If you want to get which component properties and methods, you can use this$ children[index]. Subcomponent properties / f method

Sample Text component

<script>
    export default {
        name:'test',
        data() {
            return {
                datas:"I am a subcomponent value"
            }
        },
        props:{
            obj:Object,
            info: [String,Number]
        },
        methods:{
            getValue(){
                console.log('I am Test1')
            }
        }
    }
</script>

Example Text2 component

<template>
    <div>
        <h1>I am Test2</h1>
    </div>
</template>

<script>
    export default {
        name:'test',
        data() {
            return {
                datas:"I am Test2"
            }
        },
        created(){
         console.log( this.$parent.obj ) 
         this.$parent.getQuery()
        },
        methods:{
            getTest2(){
                console.log(this.datas)
            }
            
        }
    }
</script>

refs

<template>
  <div>
   // Bind ref to sub components  
    <Test
      ref="son"
    />
   <Test2/>
  </div>
</template>

// Get the properties and methods of sub components through the $refs example

 console.log( this.$refs.son.datas) 

 this.$refs.son.getValue()

$children

//  Get the properties and methods of sub components through $children
      this.$children[0].getValue(); // I'm Test1
      this.$children[1].getTest2();  //I'm Test2
      console.log(`---------${this.$children[1].datas}`); //I'm Test2

4. The child component obtains the properties and methods of the parent component instance through $parent

<script>
    export default {
        name:'test',
        created(){
         console.log( this.$parent.obj ) 
         this.$parent.getQuery()
        },
        
    }
</script>

5. $attrs and $listeners get the attributes and methods of the parent component instance (used when the component is nested)

$attrs: contains attribute bindings (except class and style) that are not considered (and not expected to be) props in the parent scope, and can be passed into internal components through v-bind = "$attrs". When a component does not declare any props, it contains all the parent scope bindings (except class and style).

$listeners: contains v-on event listeners in the parent scope (excluding the. native modifier). It can pass in internal components through v-on = "$listeners". It is an object that contains all event listeners acting on this component, which is equivalent to that the child component inherits the events of the parent component.

Usage scenario: when using multi-layer nested components, you can avoid using Vuex for data processing, and use v-bind="$attrs" v-on="$listeners" to facilitate business data transmission.

Parent component

<template>
    <div>
        <Test3  
        :status="status" 
        :title="title"
        @getData="getData" />
    </div>
</template>

<script>
import Test3 from "../components/Test3.vue";
    export default {
        name:'person',
        data(){
            return {
                title:'personal assembly',
                status: false
            }
        },
        methods:{
          getData(){
              console.log(this.title)
          }  
        },
        components:{
            Test3
        }
    }
</script>

Sub assembly 1

<template>
  <div>
    <h1>Test3 assembly</h1>
    <br /><br />
    // Pass the attributes and methods of the parent component to the nested sub component through $attrs (attributes, except the attributes defined in props) and $listeners (Methods)
    <Test4   v-bind="$attrs" v-on="$listeners"/>
  </div>
</template>

<script>
// Introduction of sub components   
import Test4 from "../components/Test4";
export default {
  name: "test3",
  props: ["title"],
  components: {
    Test4,
  },
  created() {
    console.log(this.$attrs);  //{status: false}
    console.log("-----------");
    console.log(this.$listeners); // {getData: ƒ}
  },
};
</script>

Socket subassembly

<template>
    <div>
        <h1>Test4 assembly</h1>
    </div>
</template>

<script>
    export default {
        name:'test4',
        created(){
            console.log('-----Test4------')
            console.log(this.$attrs) //{status: false}
            console.log(this.$listeners) // {getData: ƒ}
        }
    }
</script>

6. Value transfer between components

Import vue and export vue instances by creating a new js file; Then bind the event $emit event to the exported instance, and then listen for the triggered event through $on, so as to achieve global component data sharing.

Usage scenario:

It can transfer data in any scene, parent-child components, child parent components, sibling components and cross level components

When the communication data is relatively simple, this scheme can be adopted. If the project is relatively large, Vuex can be adopted

vue .js

/*
 * @Description: 
 * @Author: ZhangXin
 * @Date: 2021-01-22 15:48:56
 * @LastEditTime: 2021-01-22 15:51:24
 * @LastEditors: ZhangXin
 */

 import Vue from 'vue'

 export default new Vue()

Component A

<!--
 * @Description: 
 * @Author: ZhangXin
 * @Date: 2021-01-22 14:44:17
 * @LastEditTime: 2021-01-22 16:25:33
 * @LastEditors: ZhangXin
-->

<template>
    <div>  
        <button @click="changeValue">change</button>
    </div>
</template>

<script>
import zxVue from '../util/newVue.js';
    export default {
        name:'person',
        data(){
            return {
                title:'personal assembly',
                status: false
            }
        },
        methods:{
          changeValue(){
             // By binding events to vue instances
             zxVue.$emit("getTitle", this.title)   
          }  
        }
    }
</script>

Component C

<!--
 * @Description: 
 * @Author: ZhangXin
 * @Date: 2021-01-22 15:07:30
 * @LastEditTime: 2021-01-22 16:26:38
 * @LastEditors: ZhangXin
-->
<template>
  <div>
    <h1>Test4 assembly</h1>
    <h1>{{ title }}</h1>
  </div>
</template>

<script>
import zxVue from "../util/newVue";
export default {
  name: "test4",
  data() {
    return {
      title: "test4",
    };
  },
  mounted(){
    // Through vue instance$ on listens to the event name to receive the value passed by the cross level component
    zxVue.$on("getTitle", (item) => {
      this.title = item;
      console.log(item)
    });

  }
};
</script>

7. Vuex

I won't introduce it here. After that, I'll write a separate article on Vuex

8. Provide and inject enable parent components to pass values to grandchildren. (unlimited levels)

provide and inject need to be used together to allow an ancestor component to inject a dependency into all its descendants, no matter how deep the component level is, and it will always take effect when the upstream and downstream relationship is established.

provide :

Is an object or a function that returns an object The object contains attributes that can be injected into its descendants.

inject :

Is an array of strings or an object It is used to inject the parent component attribute provided by provide into child components or descendant components.

Usage scenario:

provide/inject can easily access the data of parent components across levels

# provide
//object
provide:{
    name:'test'
}
//Function that returns the object
provide(){
    return {
        name: 'test'
    }
}

#inject
inject:['name']

Parent component

<!--
 * @Description: 
 * @Author: ZhangXin
 * @Date: 2021-01-22 23:24:16
 * @LastEditTime: 2021-01-22 23:49:50
 * @LastEditors: ZhangXin
-->
<template>
    <div>
        <h1>I am the parent component</h1>
        <Son />
    </div>
</template>

<script>
import Son from '../components/son/SonOne'
    export default {
        name:'father',
        provide(){
            return {
                titleFather: 'Value of parent component'
            }
        },
        components:{
            Son
        },
        data(){
            return{
                title:'I am the parent component '
            }
        },
        
    }
</script>

Subcomponents

<template>
    <div>
        <h1>I am a descendant</h1>
       
    </div>
</template>

<script>
import SonTwo from '../son/SonTwo'
    export default {
        name:'sonone',
        components:{
           SonTwo
        },
        inject:['titleFather'],
        created(){
             console.log(`${this.titleFather}-----------SonTwo`)
        },
        data(){
            return{
                title:'I'm a subcomponent '
            }
        },
        
    }
</script>

Descendant component

<template>
    <div>
        <h1>I am a descendant</h1>
       
    </div>
</template>

<script>
import SonTwo from '../son/SonTwo'
    export default {
        name:'sonone',
        components:{
           SonTwo
        },
        inject:['titleFather'],
        created(){
             console.log(`${this.titleFather}-----------SonTwo`)
        },
        data(){
            return{
                title:'I'm a subcomponent '
            }
        },
        
    }
</script>