I took some time to sort out the communication methods between Vue components, and then I wanted to sort out the notes by using the technology.

Prop the value

Using range

Parent component passes value to child component.

Method of use

The parent component

<template> <div id="app"> <div class="app"> <div class="title">App.vue</div> </div> <! < Component1 :text=" Component1 "/> </div> </template> export default {name: 'App', components: Component1; { Component1, }, data(){ return{ text1:"Text From App.vue", } } } </script>Copy the code

Child components

<template> <div class="component1"> <div class="title">Component1</div> <div> <! <span class="text-bold"> <span class="text-bold"> </span> {{text}} </div> </div> </template> <script> export default { name: {text:{type:String}},} </script>Copy the code

Results show

Pay attention to

The value passed by the parent component to the child component through the Prop is a one-way data flow, so when the parent component changes the value, the child component will also update the data. A child component should not change a prop internally. If you can do so, Vue does not recommend it and will issue a warning on the console.

V-on event binding

Using range

The child component calls the parent component method.

Method of use

The parent component

<template> <div id="app"> <div class="title"> app.vue </div> <div> < class="text-bold">count: </span> {{count}} </div> </div> <! < Component1 @componentcount =" Component1 "/> </div> </template> <script> import Component1 from "@/components/Component1"; export default { name: 'App', components: { Component1 }, data(){ return{ count:0 } }, methods:{ addCount(){ this.count++; } } } </script>Copy the code

Child components

<template> <div class="component1"> <div class="title">Component1</div> <! < button@click ="addParentCount"> add count of app. vue </button> </div> </template> <script> export default { name: "Component1", methods:{this.$emit(' Component1 ')}}} </script>Copy the code

Results show

Pay attention to

The first argument to this.$emit() is the EventName bound to the event, and from the second argument to the function, multiple parameter values can be passed, meaning that values can be passed from the child component to the parent component through this method.

Ref component registration

Scope of application

The parent component gets the child’s value or calls the child’s method.

Method of use

The parent component

<template> <div id="app"> <div class="app"> <div class="title">App.vue</div> <! <span class="text-bold">text: </span> {{text2}} </div> <! --> < button@click ="ChildrenCount"> add count of component1. vue </button> </div> <! <component1 ="component1" /> </div> </template> <script> import component1 from "@/components/Component1"; export default { name: 'App', components: { Component1, }, data(){ return{ text2:'' } }, Mounted () {/ / obtain the subcomponents text1 enclosing text2. = this.$refs.com ponent1 text1 | | '. }, methods:{// call the child component method ChildrenCount(){this.codes.ponent1.addCount (); } } } </script>Copy the code

Child components

<div class="component1"> <div class="component1"> <div class="text-bold">count: </span> {{count}} </div> </div> </template> <script> export default { name: "Component1", data(){return{text1: 'Component1. Vue ', count: 0}}, methods:{// the parent component calls this method addCount(){this.count++; } } } </script>Copy the code

The effect

Pay attention to

This.$refs is filled after the component is rendered. Therefore, this.$refs cannot be used on computed properties.

EventBus indicates the EventBus

Using range

Event invocation between any component.

Method of use

Initialize the EventBus

There are two ways to initialize an EventBus. The first way is to create a new eventbus.js. The content is as follows:

import Vue from 'vue'
export const EventBus = new Vue()
Copy the code

The file is then imported into both components when used.

import { EventBus } from ".. /eventBus.js";
Copy the code

The second way is to register EventBus globally.

Under the project main.js file, insert the registration code:

Vue.prototype.$EventBus = new Vue()
Copy the code

It can then be used via this.$EventBus call.

The following cases are implemented using the second method.

The first component

<template> <div class="component2"> <div class="title">Component2</div> <! <div> <input type="number" placeholder=" number..." v-model="value"> </div> <! --> < button@click =" Component1 "> </button> </div> </template> <script> export default { name: "Component2", data() {return {value: ""}}, methods:{// Register changeCount for EventBus, ChangeComponent1Count (){this.$eventbus. $emit("changeCount",this.value)}}} </script>Copy the code

The second component

<div class="component1"> <div class="component1"> <div class="text-bold">count: </span> {{count}} </div> </div> </template> <script> export default { name: "Component1", data(){ return{ count: 0}}, // Mounted to receive changeCount event Mounted (){this.$eventbus. $on('changeCount',(value)=> this.count = value); } } </script>Copy the code

The effect

Pay attention to

Although the concept of using An EventBus as a bridge in Vue, as if all components share a common event center to which they can register to send or receive events, allowing all components to notify each other in parallel, it can be a “disaster” that is difficult to maintain if not used properly.

Vue is a single-page application, and if you refresh a page, the EventBus associated with it will be removed, which can cause business to fail. In addition, if the business has repeated operations of the page, EventBus will be triggered many times when listening, is also a very big risk. This is where we need to manage EventBus in the project. This is usually used to remove EventBus event listeners when a vUE page is destroyed.

To remove EventBus event listener, perform the following steps:

// Remove the specified event
this.$EventBus.$off('changeCount')

// Remove all events
this.$EventBus.$off()
Copy the code

$parent and $children

Using range

Event calls and values are passed through the parent and child components nested in slots.

Method of use

App.vue

<template>
  <div id="app">
      <component3>
          <component4></component4>
      </component3>
  </div>
</template>

<script>
import Component3 from "@/components/Component3";
import Component4 from "@/components/Component4";

export default {
    name: 'App',
    components: {
        Component3,
        Component4,
    }
}
</script>
Copy the code

The parent component

<template> <div class="component3"> <div class="title">Component3</div> <! --> <div> <span class="text-bold">text: </span> {{text2}} <div> <div> <span class="text-bold">count: </span> {{count}} </div> <! --> < button@click ="addChildrenCount"> add count of component4. vue </button> <! Export default {name: "Component3", data() {return {text1: $children[0].text1; $children[0].text1; $children[0].text1; $on("changeCount",value => this.count = value); $on("changeCount",value => this.count = value); }, methods:{addCount (){this.$children[0].$emit('addCount'); } } } </script>Copy the code

Child components

<template> <div class="component4"> <div class="title">Component4</div> <! --> <div> <span class="text-bold">text: </span> {{text2}} <div> <div> <span class="text-bold">count: </span> {{count}} </div> <div> <input type="number" placeholder="Number..." v-model="value"> </div> <! --> < button@click ="changeParentCount"> </button> </div> </template> <script> export default { name: "Component4", data() { return { text1: 'Text From Component4.vue', text2:'', count: }}, mounted() {this.text2 = this.parent-text1; $on('addCount',() => this.count++); }, methods:{changeParentCount(){// Call the parent's changeCount method, $emit('changeCount',this.value)},}} </script>Copy the code

The effect

Pay attention to

Like $refs, $parent and $Children are populated after the component is rendered and therefore cannot be used on computed properties.

$children returns an array. A parent component may have multiple children, but a child component can only have one parent.

Dojo.provide and inject

Using range

A parent component passes values and methods to any descendant component, suitable for normal nesting and slot nesting.

Method of use

App.vue

<template>
  <div id="app">
      <component3>
          <component4>
              <component5></component5>
          </component4>
      </component3>
  </div>
</template>

<script>
import Component3 from "@/components/Component3";
import Component4 from "@/components/Component4";
import Component5 from "@/components/Component5";

export default {
    name: 'App',
    components: {
        Component3,
        Component4,
        Component5,
    },
}
</script>
Copy the code

The parent component

<div class="component3"> <div class="component3"> <div class="text-bold">count: </span> {{count}} </div> <! -- slot --> </slot> </div> </template> <script> export default {name: Thisprovide (){return{text:this.text1, this.text3: this.component3}}, this.component3 :this.text1, this.component3}} methods:{ addCount(){ this.count++; } } } </script>Copy the code

Child components

<template> <div class="component4"> <div class="component4"> <span class="text-bold"> <span class="text-bold"> </span> {{text}} </div> <slot></slot> </div> </template> <script> export default { name: Inject :[' Component4 ']} </script>Copy the code

Sun components

<template> <div class="component5"> <div class="title">Component5</div> <! - according to the component's text value -- -- > < div > < span class = "text - bold" > text: < / span > {{text}} < / div > <! < button@click =" Component3. Vue "> </button> </div> </template> <script> export default { name: Inject :[' component3','component3']; AddGrandParentCount (){this.ponent3.addCount (); this.ponent3.addCount (); } } } </script>Copy the code

The effect

$attrs and $listeners

Using range

The grandchild gets the value of the grandparent or calls the grandparent event.

Method of use

Progenitor components

<div class="component6"> <div class="component6"> <div class="text-bold">count: </span> {{count}} </div> <! <component7: component1 ="text" :text2="text" @addCount="addCount" /> </div> </template> <script> import Component7 from "@/components/Component7"; export default { name: "Component6", components:{ Component7 }, data() { return { text: 'Text From Component6.vue', count: 0 } }, methods:{ addCount(){ this.count ++ } } } </script>Copy the code

The parent component

<div class="component7"> <div class="component7"> <div class="component7"> </span> {{text1}} </div> <! -- bind an attribute not identified by the parent prop to the child component, /> </div> </template> <script> import component8 from /> </div> </template> <script> import component8 from "@/components/Component8"; export default { name: {Component8}} </script> </script> </script>Copy the code

Sun components

<div class="component8"> <div class="component8"> <div class="text-bold">text: </span> {{text2}} </div> <button @click="addGrandparentCount"> add count of Component6.vue </button> </div> </template> <script> export default { name: Text2 props:{text2:{type:String},} $emit('addCount') {this.$emit('addCount'); } } } </script>Copy the code

The effect

Pay attention to

$attrs contains attribute bindings in the parent scope that are not identified (and retrieved) as prop (except for class and style). Therefore, when text1 has been obtained by the quilt component prop, the sun component is not able to obtain Text1.