Transfer of parent and grand components in Vue

Foreword

When multi-level components are nested and data needs to be transferred, the commonly used method is through vuex. If you only pass data without intermediate processing, use vuex processing, it is a bit killing the chicken. Version 2.4 of Vue provides another method, using v-bind = ”$ attrs”, to pass attributes that are not considered as props property bindings in the parent component to the child component, and are usually used together with the option interitAttrs. The reason for mentioning these two attributes is that the emergence of the two makes the communication between components across components become concise and business clear without relying on vuex and event bus.

First analyze the following application scenarios:

Communication between A component and B component: (Father-child component)

As shown in the figure above, the three components A, B, and C are nested in sequence. According to Vue's development habits, parent-child component communication can be achieved in the following ways:

A to B is passed to the sub-components through props, and B to A is implemented through the $ emit in the B component and the v-on in the A component.
By setting the global Vuex shared state, the data is calculated by computed attributes and commit mutation. Get and update to achieve the purpose of communication between parent and child components.
Vue Event Bus uses Vue instances to monitor and publish events, and to communicate between components.
Often when the data does not need a global situation but only the parent-child components communicate, the first way can be satisfied.

Communication between A and C components: (across multiple levels of component nesting relationship)

As shown in the figure above, the A component and the C component are nested across multiple levels of components. In the past, if communication between the two was needed, they were often implemented in the following ways:

With the transfer of B components, props are transmitted in order from top to bottom, and from bottom to top, the transmission of the $ emit event achieves the effect of cross-level component communication.
With the help of Vuex's global state sharing
Vue Event Bus, Vue instances are used to monitor events And release, to achieve the transfer between components.
Obviously, the first method, through props and $ emit, makes the business logic between the components bloated, and component B only serves as a transit station. If the second Vuex method is used, in some cases it seems a bit overkill, (just to achieve a data transfer between components, not the concept of data sharing). The use of the third situation is found in actual project operations. If the management of event monitoring and release is not achieved, it is often easy to cause confusion of data flow. In a multi-person collaboration project, it is not conducive to project maintenance.

The emergence of $ attrs and $ listeners solves the problem of the first case. In the process of props and events passing through B components, there is no need to write extra code, just pass $ attrs and $ listeners up or down. can.

The sample code is
as follows:

A component (App.vue)

<template>
   <div id="app">
   <child1
     :p-child1="child1"
     :p-child2="child2"
     v-on:test1="onTest1" //此处监听了两个事件,可以在B组件或者C组件中直接触发
     v-on:test2="onTest2"> 
   </child1>
   </div>
</template>
<script>
   import Child1 from './Child1.vue';
   export default {
     data () {
     return {};
   },
   components: { Child1 },
   methods: {
     onTest1 () {
       console.log('test1 running...');
     },
     onTest2 () {
       console.log('test2 running');
       }
     }
   };
</script>

B component (Child1.vue)

<template>
   <div class="child-1">
   <p>in child1:</p>
   <p>props: {{pChild1}}</p>
   <p>$attrs: {{$attrs}}</p>
   <hr>
   <!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
   <!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
 <child2 v-bind="$attrs" v-on="$listeners"></child2>
 </div>
</template>
<script>
   import Child2 from './Child2.vue';
   export default {
   props: ['pChild1'],
     data () {
     return {};
   },
    inheritAttrs: false,
    components: { Child2 },
     mounted () {
       this.$emit('test1');
     }
 	};
</script>

result:

in child1:

props: v_child1

$attrs: { “p-child2”: “v_child2”}

C component (Child2.vue)

<template>
   <div class="child-2">
   <p>in child2:</p>
   <p>props: {{pChild2}}</p>
   <p>$attrs: {{$attrs}}</p>
   <hr>
   </div>
</template>
<script>
   export default {
   props: ['pChild2'],
     data () {
       return {};
     },
   inheritAttrs: false,
     mounted () {
       this.$emit('test2');
    }
   };
</script>

result:

in child2:

props: v_child2

$attrs: {}

Summary of knowledge

$ attrs
contains feature bindings (except class and style) that are not considered (and are not expected) props in the parent scope. When a component does not declare any props, it will contain all the bindings of the parent scope (except class and style), and can be passed into the internal component through v-bind = ”$ attrs”-when creating a higher-level component Is very useful.

// Human words: Introduce the Sun component in the child component, and pass the props data through the v-bind = "$ attrs" declaration. If the data is passed by the props declaration, only the undeclared components can be obtained in the Sun component. data

$listeners

Contains v-on event listeners in parent scope (without .native decorator). It can be passed to internal components via v-on = ”$ listeners”-very useful when creating higher-level components.

// Human words: Introduce the grandchild component in the child component and declare it through v-on = "$ listeners", which allows the grandchild component to emit events for the parent component to listen to

inheritAttrs
By default, attribute bindings that are not considered props in the parent scope will "fall back" and be applied to the root element of the child component as ordinary HTML features. When writing a component that wraps a target element or another component, this may not always conform to the expected behavior. By setting inheritAttrs to false, these default behaviors will be removed. And through (also added in 2.4) instance attribute $ attrs can make these features take effect, and can be explicitly bound to non-root elements through v-bind.

// Human words: My understanding is that the default parent scope does not support cross-level transfer. By declaring inheritAttrs: false in child and grand components, props can be transferred across levels

The use of the above features can completely reduce the complexity of component cross-level props and event delivery without using Vuex and the event bus.

Guess you like

Origin www.cnblogs.com/lovecode3000/p/12709231.html