This is the 15th day of my participation in the August More Text Challenge. For details, see:August is more challenging

1. Introduction

When multiple levels of component nesting need to pass data, the usual method is through VUEX. If you just pass the data and don’t do the intermediate processing, using vuEX processing, it’s a bit of a kill.

Vue 2.4 provides an alternative, using v-bind= “$attrs” to pass properties from the parent component that are not considered to be bound with the props feature to the child component. This is usually used in conjunction with the interitAttrs option. These two attributes are mentioned because they make cross-component communication between components simple and business-clear without relying on vuEX and the event bus.

First, analyze the following application scenarios

! O5k9eu6 [3] {S) PHV2ZV1ES3T. PNG] (p6-juejin.byteimg.com/tos-cn-i-k3…).

Communication between components A and B: (parent and child components)

As shown in the figure above, components A, B and C are nested in sequence. According to the development habit of Vue, communication between parent and child components can be achieved in the following ways:

  • A to B = props; B to A = props; B to A = v-on;
  • By setting the global Vuex share status and using computed computing attributes and COMMIT mutation, data is obtained and updated to achieve communication between parent and child components.
  • Vue Event Bus, using instances of Vue, to achieve Event listening and publishing, to achieve the transmission between components;

Often the data does not need to be global situation but only the parent component communication, the use of the first method is sufficient.

Communication between components A and C: (Nested relationships across multiple levels of components)

As shown in the figure above, component A and component C are nested across multiple levels. In the past, communication between the two components is usually realized in the following ways:

  • With the transfer of component B, the props are passed from top to bottom, and the $emit event is passed from bottom to top, so as to achieve the effect of cross-level component communication.
  • Global state sharing with Vuex;
  • Vue Event Bus, uses instances of Vue to monitor and publish events, and realizes the transmission between components

The first one uses props and $emit to make the business logic between components bloated. Component B only acts as a transfer station.

The second approach to Vuex, in some cases, seems to be overused (just a data transfer between components, not a data sharing concept);

The third situation is found in the actual project operation, such as the failure to achieve good event monitoring and release management, often lead to the chaos of data flow, in a multi-person collaboration project, is not conducive to the maintenance of the project;

$attrs and $Listeners are the props and props for sending the props and events, but they can only be passed up or down.Copy the code

2. Knowledge

InheritAttrs: The default value is true, inheritAttrs applies all parent attributes (except the props specific binding) to the root element of the child component as a normal HTML feature. Set inheritAttrs if you don’t want the root element of the component to inherit: False, but the class attribute is inherited. (Simply put, inheritAttrs: true inherits all attributes except props; [inheritAttrs: false] [inheritAttrs: false]

$attrs- inherits all parent attributes (except the attributes, class, and style passed by prop) and is typically used on child elements of a child component

The Listeners property, which is an object that contains all the listeners that are acting on this component, you can use the Listeners property, It is an object that contains all listeners applied to a component, and you can use v−on=”listeners” to point all event listeners to specific child elements of the component. (Equivalent to an event where the child inherits from the parent)

Example 3.

Component A (app.vue)

<template>
  <div id="app">
    <! -- We are listening for two events, which can be fired directly from component B or component C -->
    <child1  :pchild1="child1" :pchild2="child2" :pchild3="child3" @method1="onMethod1" @method2="onMethod2"></child1>
  </div>
</template>

<script>
import Child1 from "./Child1.vue";
export default {
  data() {
    return {
      child1:'1'.child2: 2.child3: {name:'child3'}}; },components: { Child1 },
  methods: {
    onMethod1(msg1) {
      console.log(`${msg1} running`);
    },
    onMethod2(msg2) {
      console.log(`${msg2} running`); ,}}};</script>
Copy the code

Component B (Child1.VUE)

<template>
  <div class="child-1">
    <h2>in child1</h2>
    <p>props: {{ pchild1 }}</p>
    <p>$attrs: {{ $attrs }}</p>
    <hr/>
    <! C: props = props > C: props = props > C: props = props > C: props = props
    <! -- Component C triggers test directly because component B uses the $Listeners property when calling component C -->
    <child2 v-bind="$attrs" v-on="$listeners"></child2>
  </div>
</template>

<script>
import Child2 from "./Child2.vue";
export default {
  data() {
    return {
      child1:'child1'  
    };
  },
  components: { Child2 },
  props: {
    pchild1: {type:String}},inheritAttrs: false.mounted() {
    this.$emit("method1".this.child1); }};</script>
Copy the code

C components (Child2. Vue)

<template>
  <div class="child-2">
    <h2>in child2:</h2>
    <p>props: {{ pChild2 }}</p>
    <p>$attrs: {{ $attrs }}</p>
    <p>pchild3Name: {{ $attrs.pchild3.name }}</p>
    <hr/>
  </div>
</template>

<script>
export default {
  data() {
    return {
      child2:'child2'
    };
  },
  props: {
    pChild2: {type:String,}},inheritAttrs: false.mounted() {
    this.$emit("method2".this.child2); }};</script>
Copy the code

The effect