12 ways of data communication between Vue components

Table of contents

1. The parent component passes data props to the child component

2. The child component passes data to the parent component (usage of $emit)

3. Brother component communication

4、ref / $refs

5. eventBus event bus ($emit / $on)

6. Dependency injection (provide/inject)

7.$parent / $children

8. $children

9. $root

10. vuex

11. $attrs / $listeners


1. The parent component passes data props to the child component

The parent component passes data to the child component through  props  , and the child component   communicates with the parent component through $emit

The characteristics of props:

  • Props can only pass values ​​from parent components to child components, and props make a one-way downstream binding between parent and child components. The data of the child component will be updated responsively as the parent component is updated.

code demo

parent component:

// 父组件
<template>
    <div id="father">
        <son :msg="msgData" :fn="myFunction"></son>
    </div>
</template>

<script>
import son from "./son.vue";
export default {
    name: father,
    data() {
        msgData: "父组件数据";
    },
    methods: {
        myFunction() {
            console.log("vue");
        }
    },
    components: {
        son
    }
};
</script>

Subassembly:

// 子组件
<template>
    <div id="son">
        <p>{
   
   {msg}}</p>
        <button @click="fn">按钮</button>
    </div>
</template>
<script>
export default {
    name: "son",
    props: ["msg", "fn"]
};
</script>

2. The child component passes data to the parent component (usage of $emit)

Features of $emit:

  • $emit binds a custom event, when the event is executed, the parameters are passed to the parent component, and the parent component listens and receives parameters through v-on

usage:

parent component:

// 父组件
<template>
  <div class="section">
    <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
    <p>{
   
   {currentIndex}}</p>
  </div>
</template>

<script>
import comArticle from './test/article.vue'
export default {
  name: 'comArticle',
  components: { comArticle },
  data() {
    return {
      currentIndex: -1,
      articleList: ['红楼梦', '西游记', '三国演义']
    }
  },
  methods: {
    onEmitIndex(idx) {
      this.currentIndex = idx
    }
  }
}
</script>

Subassembly:

//子组件
<template>
  <div>
    <div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{
   
   {item}}</div>
  </div>
</template>

<script>
export default {
  props: ['articles'],
  methods: {
    emitIndex(index) {
      this.$emit('onEmitIndex', index) // 触发父组件的方法,并传递参数index
    }
  }
}
</script>

3. Brother component communication

Brother component communication can interact with parent components

A component B component

1. The A component data is passed to the common parent component and then passed to the B component after the parent component accepts it 

2. Through $parent + $refs, the parent component is used as an intermediary to obtain sibling components, and communication is also possible.

4、ref / $refs

This way is also to achieve communication between parent and child components

ref: This attribute is used on subcomponents, and its use points to the instance of the subcomponent, and the data and methods of the component can be accessed through the instance

usage:

In child component:

export default {
  data () {
    return {
      name: 'JavaScript'
    }
  },
  methods: {
    sayHello () {
      console.log('hello')
    }
  }
}

In parent component:

<template>
调用子组件使用ref 获取子组件实例
  <child ref="child"></component-a>
</template>
<script>
  import child from './child.vue'
  export default {
    components: { child },
    mounted () {
      console.log(this.$refs.child.name);  // JavaScript 获取子组件数据
      this.$refs.child.sayHello();  // hello  调用子组件的方法
    }
  }
</script>

5. eventBus event bus ($emit / $on)

The eventBus event bus is suitable for communication between parent-child components and non-parent-child components , etc. The usage steps are as follows:

Vue event bus ( eventBus ), by creating an empty vue instance as a global event bus, use it to trigger events and listen to events, so as to realize communication between any components, including parent-child, intergenerational, sibling components


(1) Create communication between event center management components

// main.js
Vue.prototype.$bus = new Vue()
// child2
    this.$bus.$emit('bus', 'bus传值,组件2传过来的')
// child2
    this.$bus.$on('bus', (msg)=> {
      console.log('msg', msg)
    })

(2) Sending events Suppose there are two components home About

 


(3) Receive events

In the above code, this is equivalent to storing the count value in the event bus, which can be directly accessed in other components. The event bus is equivalent to a bridge, and no components communicate through it. Although it seems relatively simple, this method also has some invariants. If the project is too large, using this method for communication will be difficult to maintain later .
Vue3 is no longer used and abolished

6. Dependency injection (provide/inject)


This method is dependency injection in vue, which is used for communication between parent and child components. Of course, the father and son mentioned here are not necessarily real father and son, but also grandparents and grandchildren. In the case of deep layers, this method can be used to pass values. There is no need to pass data layer by layer.

Provide and inject are two hooks provided by vue, which are at the same level as data and methods. And the written form of provide is the same as data.

The provide hook is used to send data or methods.
The inject hook is used to receive data or methods
Usage:
In the parent component:
 

provide() { 
    return {     
        num: this.num  
    };
}

In the subcomponent:

inject: ['num']

There is another way of writing, which can access all properties in the parent component:

provide() {
 return {
    app: this
  };
}
data() {
 return {
    num: 1
  };
}

inject: ['app']
console.log(this.app.num)

7.$parent / $children

  • Using $parent allows the component to access the instance of the parent component (the properties and methods of the previous parent component are accessed).
  • Using $children allows components to access instances of child components, however, $children does not guarantee order, and the accessed data is not responsive.

usage:

In the subcomponent:

<template>
  <div>
    <span>{
   
   {message}}</span>
    <p>获取父组件的值为:  {
   
   {parentVal}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Vue'
    }
  },
  computed:{
    parentVal(){
      return this.$parent.msg;
    }
  }
}
</script>

8. $children

In the parent component:

<template>
  <div class="hello_world">
    <div>{
   
   {msg}}</div>
    <child></child>
    <button @click="change">点击改变子组件值</button>
  </div>
</template>

<script>
import child from './child.vue'
export default {
  components: { child },
  data() {
    return {
      msg: 'Welcome'
    }
  },
  methods: {
    change() {
      // 获取到子组件
      this.$children[0].message = 'JavaScript'
    }
  }
}
</script>

In the above code, the child component gets the parentVal value of the parent component, and the parent component changes the value of message in the child component.

Notice:

Accessed through $parent is the instance of the parent component of the previous level. You can use $root to access the instance of the root component. Use
$children in the component to get the instances of all child components. It is an array and is null. Sequentially,
taking $parent on the root component #app will get an instance of new Vue(), taking $parent on this instance will get undefined, and taking $children in the bottom subcomponent is an empty array of $
children Value is an array and $parent is an object
 

9. $root

Data data hanging on the root component instance --- not recommended

Subcomponents can be accessed through this.$root.xxx

Any child component access

 

10. vuex

11. $attrs

12. $listeners

$attrs

Used to pass data from parent component to grandchild component

$listeners

Used by grandson components to pass data to parent components

Consider a scenario where A is the parent of component B and B is the parent of component C. If you want component A to pass data to component C, which method should you use in this case of passing data from generation to generation?

If you use props/ $emit to pass level by level, it can indeed be completed, but it is more complicated; if you use an event bus, it will be troublesome to maintain when multiple people are developing or the project is large; if you use vuex, if only It is to pass data, which may be a bit wasteful.

In response to the above situation, vue introduces $attrs / $listeners, which is the cross-generational communication between real components.

$attrs : Inherit all parent component properties (except properties passed by props, class and style), generally used on sub-elements of sub-components
$listeners: This property is an object that contains all listeners acting on this component device, you can use v-on=" $listeners " to direct all event listeners to a specific child element of this component. (Equivalent to child components inheriting events from parent components)
 

Usage of $attrs / $listeners:

parent component

son1 component

Son2 component

In the above code:

  • The reason why the test can be directly triggered in the C component is that when the B component calls the C component, the v-on is used to bind the $listeners property
  • In component B, bind the $attrs attribute through v-bind, and component C can directly obtain the props passed down from component A (except for props declared in component B)

 

Guess you like

Origin blog.csdn.net/xm1037782843/article/details/128027132