preface

Data communication between components is very important to Vue, and Vue component communication comes up frequently in interviews. How do components communicate with each other? In order to have a deeper understanding of the data communication of components, this paper specifically summarizes the communication scenarios between components and the way of communication and implementation.

Component communication generally has the following scenarios:

  • Parent-child component communication
  • Intergenerational component communication
  • Sibling communication
  • Communicate across routed components

How to choose effective communication mode to realize data communication among components according to different application scenarios;

The following article describes how the following seven components communicate.

Props /emit pass parameter

Used to introduce

The props/ EMIT parameter is a basic component communication method. The parent component can communicate with its children through props, and the children can communicate with the parent component through emit.

Usage scenarios

  • Parent-child component communication

Method of use

1. The parent component sends parameters to the child component

The parent component communicates by defining the props parameters in the child component and passing in the parameter properties defined in the child component.

## Vue 3.x


  / / the parent component
  <template>
    <child :message="msg"></child>
  </template>
  <script setup>
  import { ref } from 'vue'
  import Child from './Child.vue'

  const msg = ref('hello vue3.x')

  </script>


  / / child component
  <template>
    <div>
      <span>{{ message }}</span>
    </div>
  </template>
  <script setup>
  import { defineProps } from 'vue'

  const props = defineProps({
    message: {
      type: String}})</script>

Copy the code
## Vue 2.x


  / / the parent component
  <template>
    <child :message="message"></child>
  </template>
  <script>
  import Child from './Child.vue'

  export default {
    components: {
      Child
    },
    data() {
      return {
        message: 'hello vue2.x'}}}</script>


  / / child component
  <template>
    <div>
      <span>{{message}}</span>
    </div>
  </template>
  <script>
  export default {
    props: {
      message: {
        type: String.default: 'test'}}}</script>

Copy the code

2. The child component sends parameters to the parent component

Vue uses the on/on/on/emit mode to allow the child component to send parameters to the parent component. The child component uses $emit to bind a custom event to the parent component. When the child component executes the statement, the parameter is passed to the parent component. The parent listens for the child’s custom events via $on to get the parameters passed by the child.

## vue3.x


  / / the parent component
  <template>
    count:{{num}}
    <child :num="num" @addCount="addCount"></child>
  </template>
  <script setup>
    import { ref } from 'vue'
    import Child from './Child.vue'

    const num = ref(100)
    function addCount(res) {
      num.value = res
    }
  </script>


  / / child component
  <template>
    <div>
      <button type="primary" @click="addCount">count++</button>
    </div>
  </template>
  <script setup>

  const props = defineProps({
    num: {
      type: Number.default: 0}})const emit = defineEmits(['addCount'])
  function addCount() {
    emit('addCount', props.num + 1)}</script>

Copy the code
## vue2.x
  / / the parent component
  <template>
    count:{{num}}
    <child :num="num" @addCount="addCount"></child>
  </template>
  <script>
  import Child from './Child.vue'

  export default {
    components: {
      Child
    },
    data() {
      return {
        num: 100}},methods: {addCount(res) {
        this.num = res
      }
    }
  }
  </script>

  / / child component
  <template>
    <div>
      <button type="primary" @click="addCount">count++</button>
    </div>
  </template>
  <script>
    export default {
      props: {
        num: {
          type: Number.default: 0}},methods: {addCount() {
          this.$emit('addCount'.this.num + 1)}}}</script>

Copy the code

Used to summarize

1. The most common communication mode of parent-child components. 2. Supports parameter verification. 3. Emit will only trigger listening events for the parent component. 4. It is not suitable for transferring parameters of multi-level components. Parameters need to be transferred layer by layer.Copy the code

Second, the eventBus

Used to introduce

An EventBus, also known as an EventBus, can be used to communicate between components. Similar to VuEX, all components share an event center. This event center is used to manage events and send and receive events when needed. By sharing a vUE instance, use the instance’s $ON and $EMIT for data transfer.

Usage scenarios

  • Intergenerational component communication
  • Sibling communication

Method of use

## vue3. X Vue3 completely removes the $on, $OFF, and $once methods from the instance, so vue3 does not support eventBus. Third party libraries are officially recommended: Mitt, Tiny-EmitterCopy the code
## vue2.x


  // eventBus.js
  const eventBus = new Vue()
  export default eventBus



  / / A component
  import eventBus from './eventBus'
  // Send messages via emit
  eventBus.$emit('message')



  / / B component
  import eventBus from './eventBus'
  // Receive messages via $on
  eventBus.$on('message'.() = > {
    console.log('Message received! ')})// Unbind listeners when the component is destroyed
  beforeDestroy () {\
    eventBus.$off('message')\
  }



Copy the code

Used to summarize

1. Communication between sibling components or any two components in the scenario of multi-layer nested components. 2. The $on event is not destroyed automatically and needs to be destroyed manually. We can unbind listeners in beforeDestroy to avoid repeated firing. 3. Suitable for simple scenarios, vuEX is recommended for complex scenarios.Copy the code

Third, vuex

Used to introduce

Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way. Vuex consists of the following parts: globally unique state management repository (state), simultaneous operations (mutations), asynchronous operations (Actions), cache dependencies (getters) and modules. Visit Vuex’s official website for detailed usage

Usage scenarios

  • Intergenerational component communication
  • Sibling communication
  • Communicate across routed components

Method of use

// Create a store object
import Vue from 'vue';
import Vuex from 'vuex';
import persistedState from 'vuex-persistedstate'
Vue.use(Vuex);
const store = new Vuex.Store({
  state: {name:' '.age:0
    },
    // Data filtering cache dependency
    getters: {getUserInfo(state){
        return `name=${state.name},age=${state.age}`}},// Synchronize the operation
    mutation: {SET_NAME: (state, name) = > {
        state.name = name
      },
      SET_AGE: (state, age) = > {
        state.age = age
      }
    },
    // Asynchronous operation
    actions: {setName({ commit }, name) {
        commit('SET_NAME', name)
      }
    },
    // Data state persistence plug-in to prevent page refresh data loss
    plugins: [persistedState({ storage: window.sessionStorage })]
})

export defaultUse method in store ## component// Synchronize the request
this.$store.commit('I'm a rookie')
// Asynchronous request
this.$store.dispatch('setName'.'I'm a rookie')
// getter
this.$store.getters.getUserInfo

Copy the code

Used to summarize

1. Communication between any component and communication between multiple components. 2. Communicate across routing components. 3. Refresh the browser. Vuex data may be lost. 4. Suitable for large projects with complex scenarios, not recommended for simple service scenarios.Copy the code

Four, ref

Used to introduce

$refs lets you get an instance of the child component and invoke the methods in the instance to communicate with the parent component.

Usage scenarios

  • Parent-child component communication

Method of use

  / / the parent component
  <template>
    <div id="app">
      count:{{ num }}
      <button @click="handle">Get the child component instance through ref</button>
      <child ref="child"></child>
    </div>
  </template>
  <script>
    import Child from "./Child.vue";

    export default {
      components: {
        Child
      },
      data() {
        return {
          num: 100
        };
      },
      methods: {
        handle() {
          this.num = this.$refs.child.num; }}}</script>


  / / child component
  <template>
    <div>
      {{ num }}
      <button type="primary" @click="addCount">count++</button>
    </div>
  </template>
  <script>
    export default {
      data() {
        return {
          num: 0
        };
      },
      methods: {
        addCount() {
          this.num++;
        },
        getNum() {
          return this.num; }}};</script>

Copy the code

Used to summarize

1. You can retrieve a subcomponent instance in this way to retrieve all properties of the subcomponent instance or the events that call the subcomponent.Copy the code

Provide/inject

The usage description is often used for multi-layer nested component encapsulation when descendant components need to use the data methods of the top-level component. The parent component provides data methods needed by the descendant component through provide, and the descendant component receives data methods passed by the top component through Inject.

Usage scenarios

  • Intergenerational component communication

Method of use

// Top-level component
<template>
  <div id="app">
    <button @click="handle">Click on the</button>
    <child ref="child"></child>
  </div>
</template>
<script>
import Child from "./Child.vue";

export default {
  components: {
    Child
  },
  // Hint: provide and inject binding are not responsive. This is intentional. However, if you pass in a listening object, the object's properties are still responsive.
  provide() {
    return {
      foo: this.paramData // It must be an object that can be listened to
    };
  },
  data() {
    return {
      paramData: {
        color: "red"}}; },methods: {
    handle() {
      this.paramData.color = "blue"; }}};</script>


// Descendant components
<template>
  <div>
    {{ foo.color }}
  </div>
</template>
<script>
export default {
  inject: ["foo"]};</script>


Copy the code

Used to summarize

1. Communication between components across hierarchies. 2. The property passed is non-responsive. provide: { color: "green" } 3. Provide () {return {color: this.paramdata,}; provide() {return {color: this.paramdata,}; }, data() { return { paramData: { color: "red" } }; } 4. It is not recommended to pass parameters in this way in complex components. Data tracing is difficult due to access at any level.Copy the code

Six, attrs/listeners

Used to introduce

Componentnested components can use attrs/ Listeners to support additional attribute parameter delivery, such as secondary encapsulation of elementUI components to pass unwanted attributes to child components.

$attrs gets properties passed in by the parent component but not received by props

Events defined by $Listeners are on the root element of the child component, and sometimes want to be added to other elements. You can use $listerners. It contains event listeners from the parent component (except listeners with the.native modifier)

Usage scenarios

  • Parent-child component communication

Method of use

// Top-level component
<template>
  <div id="app">{{" top-level component parameter aa:" + aa}}<child :aa="aa" bb="bb" cc="cc" @parentClick="handle"></child>
  </div>
</template>
<script>
import Child from "./Child1.vue";

export default {
  components: {
    Child
  },
  data() {
    return {
      aa: "aa"
    };
  },
  methods: {
    handle(data) {
      this.aa = data; }}};</script>


/ / child component
<template>
  <div>
    <p>Subcomponent PROP parameter [AA]: {{AA}}</p>
    <p>Child component non-prop parameter [$attrs]: {{$attrs}}</p>

    <child :cc="$attrs.cc" v-on="$listeners"></child>
  </div>
</template>
<script>
import Child from "./Child2.vue";

export default {
  components: {
    Child
  },
  props: {
    aa: String}};</script>



// Grandchild component
<template>
  <div>
    <p>[cc]: {{cc}}</p>
    <button @click="handle">Click pass parameter top component</button>
  </div>
</template>
<script>
export default {
  name: "c1".props: {
    cc: String
  },
  methods: {
    handle() {
      this.$emit("parentClick"."Subcomponent parameter Transfer"); }}}</script>
Copy the code

Used to summarize

1. Multilevel component nesting requires passing data, if there are too many parameters and only data is being passed, the parent component can pass parameters not defined by prop to the grandson component via $attr. 2. Parent functions can be passed to child components via $Listeners, and child components can emit parameters via the emit trigger.Copy the code

$child / $parent

Used to introduce

By the parent/parent/parent/children can get a component instance, father and son to call the data in the instance method, realize parent-child communication components (not recommended).

Usage scenarios

I haven't used this method yetCopy the code

Method of use

// Get the parent component instance
this.$parent
// Get the child component instance
this.$children
// Get the root component instance
this.$root
Copy the code

Used to summarize

This method has not been used for the time being, so it is not summarized hereCopy the code