Writing in the front
There are three communication modes: parent-child communication, sibling communication and intergenerational communication
7 component communication modes:
-
props && $emit
-
parent && root && $children
-
$attrs
-
ref
-
provide && inject
-
EventBus
-
vuex
1. props && $emit
<! -- Example 1: -->
<body>
<div id="app">
<! MyCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn
<! Cpn-list ="list" --> cpn-bind :cpn-list="list" -->
<! Cpn-list is an attribute defined in the props of the child component, which is used to receive the list passed by the parent component.
<my-cpn :cpn-list="list" :cpn-pers-info="persInfo"></my-cpn>
</div>
<script>
Vue.component('myCpn', {
// In the template of the child component, use the properties in the child component props
template: ` < div > < h1 > I am a child component myCpn < / h1 > < h1 > receives the data: {{cpnList}} < / h1 > < h1 > receives the data: {{cpnPersInfo}} < / h1 > < / div > `.props: ['cpnList'.'cpnPersInfo']});var vm = new Vue({
el: "#app".data() {
return {
list: ['digital'.'goods'.'travel'].persInfo: {
name: 'Bob'.age: 20}}}});</script>
</body>
Copy the code
<! -- Example 1: -->
<body>
<! -- Subcomponent template -->
<template id="son">
<div>
<! -- 1. The child component triggers the event function by clicking on the event -->
<button v-for="item of categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<! Parent component template -->
<div id="app">
<! The parent component listens for the child component's custom event item-click. Note that the function for the custom event does not have an event object, but it will pass the child component's data item by default.
<cpn-button @item-click="cpnClick"></cpn-button>
</div>
<script>
/ / child component
Vue.component('cpnButton', {
data() {
return {
categories: [{id: '1'.name: 'goods' },
{ id: '2'.name: 'technology' },
{ id: '3'.name: 'outdoor'},]}},template: '#son'.methods: {
btnClick(item) {
// 2. The child component will emit a custom event via this.$emit(custom event name, passed to the parent component). Custom event names should be delimited with a lowercase dash
this.$emit('item-click', item)
}
}
})
// Parent component instance
new Vue({
el: '#app'.methods: {
// 4. The custom event function listened by the parent component receives the item data passed by the child component
cpnClick(item) {
console.log("-", item)
}
}
})
</script>
</body>
Copy the code
2. $parent && $root && $children
-
This.$parent: It is possible to access the parent component, but this is not recommended. This would break the reusability of the child component, such as modifying the name property of the parent component in the child, but other components of B reference the child, and B does not have the name property. There is no decoupling
-
This.$root: accesses the root instance directly
-
This.$children: is an array containing all direct child component objects; For example, A, B, and C in the above example; The this.children array of A has only one element called B, but the this.children array of B has only one element called B, But B’s this.children contains a C component;
// Use the following in component A to access the msgC properties of component C
this.$children[0].$children[0].msgC
Copy the code
<! -- this.$children example -->
<body>
<div id="app">
<cpn></cpn>
<button @click="btn">button</button>
</div>
<template id="cpn">
<div>
<h1>{{message}}</h1>
</div>
</template>
<script>
var vm = new Vue({
el: "#app".data: {
message: "I'm the parent app.",},methods: {
btn() {
console.log(this.$children[0].message)
this.$children[0].show(); }},components: {
cpn: {
template: '#cpn'.data() {
return {
message: "I am a child component CPN",}},methods: {
show() {
console.log(this.message); }}}}});</script>
</body>
Copy the code
3. Communication between $attrs components
Vm. $attrs: is an object that accepts all attributes passed by the parent component.
Generally we accept properties passed by the parent component by defining the props option in the child component to accept values passed by the parent component.
Attrs contains all parent bindings (except class and style), and can contain all parent bindings (except class and style) by v−bind=” And v-bind=”attrs “will contain all parent-scoped bindings (except class and style), and you can pass in internal components via v−bind=”attrs”
If there are three generations of components A,B, and C, we want to pass property A from component A to component C, but if we use props, we will define props in the middle layer OF component B to accept the value A from component A, and then pass A, which is accepted by component B, to component C. However, component B does not use A. You still need to define the props attribute to accept; If the component has too many nested layers, the intermediate component can define too many props, resulting in waste.
Attrs can easily pass through attributes and is relatively simple to use, avoiding the pain of multiple props for intermediate components
<! -- Example 1: -->
<! -- A.vue -->
<template>
<div>I'm component A<B :msg-a="msgA" :list-a="listA"></B>
</div>
</template>
<script>
import B from "./B";
export default {
data () {
return {
msgA: 'hello msgA'.listA: ['Palm of the Five Poisonous Gods'.'My Heart is in the clouds'.'Eighteen Palms of the Dragon']}},components: {
B
}
}
</script>
<! -- B.vue -->
<template>
<div>I'm component B<C v-bind="$attrs" :msg-b="msgB"></C>
</div>
</template>
<script>
import C from "./C";
export default {
data () {
return {
msgB: 'hello msgB'}},components: {
C
}
}
</script>
<! -- C.vue -->
<template>
<div>{{msgB}} -- {{msgB}} -- {{listA}}</div>
</template>
<script>
export default {
props: ['msgA'.'msgB'.'listA']}</script>
// main.js
import Vue from "vue";
import A from "./components/A.vue";
new Vue({
render: h => h(A)
}).$mount("#app");
Copy the code
<! -- Example 2: Note -->
<! -- B.vue -->
<template>
<div>I am B component {{listA}}-- {{msgA}}<C v-bind="$attrs" :msg-b="msgB"></C>
</div>
</template>
<script>
import C from "./C";
export default {
data () {
return {
msgB: 'hello msgB'}},props: ['msgA'.'listA'].components: {
C
}
}
</script>
<! Summary of Example 2: $attrs = $attrs; $attrs = $attrs; $attrs = $attrs; $attrs = $attrs;
Copy the code
4. ref
Definition: When used on a normal DOM element, the reference refers to the DOM element. If used on a child component, the reference refers to the component instance
$ref = this.$ref = this.$ref = this. The value of the ref bound to the child component gets the instance of the child component.
$refs: this.$refs is null by default. When the ref attribute is bound to a subcomponent, the structure of this.
Note: When ref gets the component, it is not a DOM element, so you cannot directly access the attributes of the DOM element; You need the component’s $EL to get the COMPONENT’s DOM element
// This fetches the component's DOM element via the component's $el, and accesses the DOM attributes
this.$ref.xxx.$el.style.color = red
Copy the code
4.1 Access dom elements directly through ref
// Example 1: ref accesses dom elements<body>
<div id="app">// Bind the ref attribute to the p element, and the parent component VM instance can reference the p element via vm.$ref. Pref to manipulate the p element<p ref="pref" attr="ppp">I'm a p element</p>
<div>
{{ getElement() }}
</div>
</div>
<script>
var vm = new Vue({
el: '#app'.methods: {
getElement() {
// this.$refs.pref points to the p element
$refs.pref.getAttribute('attr') returns the attr attribute value on the p element
return this.$refs.pref
}
}
})
</script>
</body>
Copy the code
4.2 Access child component instances directly through ref
// Example 2: Access child component instances through ref<div id="app">
<cpn ref="cpnRef"></cpn>
<button @click="getcpn">btn</button>
<p>{{ msg }}</p>
</div>
<script>
var vm = new Vue({
el: '#app'.data() {
return {
msg: ' '}},components: {
cpn: {
template: '
I am a CPN component
'.data() {
return {
cpnMsg: "I am the cpnMsg of the CPN component"}}}},methods: {
getcpn() {
// this.$refs.cpnRef points to CPN component instances; You can simply call properties or methods of CPN components
// this.$refs.cprefref. cpnMsg retrieves the CPN subcomponent property value
this.msg = this.$refs.cpnRef.cpnMsg
}
}
})
</script>
Copy the code
5. provide && inject
React context The parent component exposes properties, methods, instances, etc., children or grandchildren… Data exposed by the parent component (properties, methods, instances, etc.) can be retrieved in Inject
Disadvantages:
- Not suitable for sibling component communication, or communication between two unrelated components
- Only the parent component can be exposed for the offspring to use; No descendant can be exposed to the parent component
Advantages: Suitable for parent components and nested deep level of grandchildren… Communication between components.
Note the following: 1. The exposed name of the provider must be the same as the name of the inject. 2. The provider must bind this in advance in the parent component to expose the method
// Provide && inject is used for communication between el-form and el-form-item
<el-form label-width="80px" :model="formData">
<el-form-item label="Name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="Age">
<el-input v-model="formData.age"></el-input>
</el-form-item>
</el-form>
Copy the code
Basic usage:
/ / the parent component
<template>
<div class="father" >
<div>The child component says to me: {{sonMes}}</div>
<div>{{grandSonMes}}</div>
<son />
</div>
</template>
<script>
import son from './son'
export default {
name:'father'.components:{
son /* Subcomponent */
},
provide(){
return {
/* Expose yourself to descendant components, where the name declared is the same as the name imported by the child component */
father:this}},data(){
return {
grandSonMes:' './* Information from the child component */
sonMes:' ' /* Information sent to child components */}},methods: {/* Receives the message from the sun component */
grandSonSay(value){
this.grandSonMes = value
},
/* Accepts child component information */
sonSay(value){
this.sonMes = value
},
},
}
</script>
Copy the code
/ / child component
<template>
<div class="son" >
<input v-model="mes" /> <button @click="send" >Say to the parent component</button>
<grandSon />
</div>
</template>
<script>
import grandSon from './grandSon'
export default {
/* Subcomponent */
name:'son'.components:{
grandSon /* Sun component */
},
data(){
return {
mes:' '}},/* Import the parent component */
inject: ['father'].methods: {send(){
this.father.sonSay(this.mes)
}
},
}
</script>
Copy the code
/ / sun components
<template>
<div class="grandSon" >
<input v-model="mes" /> <button @click="send" >Said to grandpa Component</button>
</div>
</template>
<script>
export default {
/* Sun component */
name:'grandSon'./* Introduce grandpa component */
inject: ['father'].data(){
return {
mes:' '}},methods: {send(){
this.father.grandSonSay( this.mes )
}
}
}
</script>
Copy the code
Bind this to expose methods
/ / the parent component
provide(){
return {
/* Expose communication methods to descendant components (note binding this) */
grandSonSay:this.grandSonSay.bind(this),
sonSay:this.sonSay.bind(this)}},methods: {/* Receives the message from the sun component */
grandSonSay(value){
this.grandSonMes = value
},
/* Accepts child component information */
sonSay(value){
this.sonMes = value
},
},
/ / child component
/* Introduces the parent component method */
inject: ['sonSay'].methods: {send(){
this.sonSay(this.mes)
}
},
Copy the code
6. EventBus
Advantages: The communication between any two components is not affected by the component level. When data is needed, it goes through the ON binding, and when data is sent, it emit
Disadvantages: Event component naming is not maintainable
Juejin. Cn/post / 689823…
7. vuex
Disadvantages: VuEX communication method is more complex than other methods, and if different modules need to be set up independently
Advantages:
- Resolve communication problems between two unrelated components
- Support for asynchronous component communication (Actions in VUEX allow us to do some asynchronous operations)
Question: Why can actions be asynchronous?
Resolve is used to retrieve the status of asynchronous task completion.
Juejin. Cn/post / 690600…
reference
My.oschina.net/u/3347851/b…