Writing in the front
Summary is a way of learning, learning from each other is a learning attitude. The full text summarizes 6 kinds of communication between Vue components, if there are misunderstandings, welcome to correct!
1, props / $emit
One of the most common ways to pass data between a parent and a child.
Description:
The parent component passes data to the child component through the binding property, and the child component obtains the corresponding data through the props property. The child component sends a message to the parent via the $emit event, passing its data to the parent.
Usage:
// Parent compA <template> <div> <compB :title="value"
:moreBtn="moreBtn"
@more="onMore"/>
</div>
</template>
<script>
import compB from './compB'
export default{
name: 'compA',
components:{
compB
},
data() {return {
value: ' ',
moreBtn: true
}
},
method:{
onMore(value){
console.log('value', value) // Click to see more buttons}}} </script>Copy the code
// compB <template> <div> <div class="title">{{value}}</div>
<div v-if="moreBtn" @click="handleMore"</div> </template> <script>export default{
name: 'compB'.data() {return {
}
},
props: {
title: {
type: String,
default: 'title'
},
moreBtn: {
type: Boolean,
default: false
}
}
method:{
handleMore(){
this.$emit('more'.'Click the button to see more')
}
}
}
</script>
Copy the code
The props allows a one-way data flow between the parent and child, with the state of the child changing when the parent is updated. But the reverse can make the flow of your application’s data difficult to understand.
Note that objects and arrays are passed in by reference in JavaScript, so for a prop of an array or object type, changing the object or array itself in a child component will affect the state of the parent component.
If the data passed through prop is an array or an object, it is possible to change the value of the parent object, but it is not recommended. If you pass a string and change the value of the parent component, Vue will issue a warning in the browser console.
In some cases, the child component may need to change the value of the parent component. It is recommended to use the.sync syntax sugar added in version (2.3.0+).
Usage:
// A.vue
<template>
<add-modal
v-if="modalVisiable"
:visiable.sync='modalVisiable'
@submit="saveForm"
/>
</template>
<script>
export default {
name: 'A'.data() {return {
modalVisiable: false
}
}
}
</script>
Copy the code
// B.vue
<template>
<Modal
v-model="show"
width="600"
title="Bounced"
:loading='true'
@on-cancel="$emit('update:visiable', false)"
>
</Modal>
</template>
<script>
export default {
name: 'A'.data() {return {
show: false,}},created(){
this.show = this.visiable
},
props: {
visiable: {
type: Boolean,
default: false
}
},
}
</script>
Copy the code
$emit(‘update:visiable’, false) to change the state of the parent element
2, $emit / $on
EventBus indicates the eventBus
Description:
This is done by creating an empty VUE instance that acts as the $EMIT event handler (event bus), which triggers and listens for events, facilitating communication between any component, including parent, sibling, and generational components.
In the following figure, we want to realize that components A and C transmit data to component B.
Usage:
<! --home.vue--> <template> <div> <div> I am the parent element, my num value is: {{num}}</div> <a-comp :event="bus" :num.sync='num'></a-comp>
<c-comp :event="bus" :num='num'></c-comp>
<b-comp :event="bus"></b-comp>
</div>
</template>
<script>
import Vue from 'vue';
import aComp from './a.vue';
import bComp from './b.vue';
import cComp from './c.vue'; // Create an empty vue instance const bus = new vue ();export default {
'name': 'example'.data() {
return {
bus,
'num': 1}; },'components': {
aComp,
bComp,
cComp
}
};
</script>
Copy the code
<! --a.vue--> <template> <div class="a-content"<el-button style = "box-sizing: border-box; word-wrap: break-word! Important;type="primary" @click="send"</el-button> </div> </template> <script>export default {
'name': 'aComp'.'props': [
'event'.'num'].data() {
return {'nb': 0};
},
created() {
this.nb = this.num;
},
'methods': {
send() {
this.nb = this.nb + 1;
this.$emit('update:num', this.nb); / / by$emitTo trigger the phone-aThis event. The event.$emit('phone-a'.'I'm component A.', this.nb); }}}; </script>Copy the code
<! --c.vue--> <template> <div> I am component C, <el-buttontype="primary" @click="send"</el-button> </div> </template> <script>export default {
'name': 'cComp'.'props': [
'event'.'num'].data() {
return {};
},
'methods': {
send() {
console.log(this.num);
this.event.$emit('phone-c', 'I'm component C${this.num}`); }}}; </script>Copy the code
<! --b.vue--> <template> <div class="b-content"> < div > I am A component B, and I will receive the component A and component C < / div > < div > A: {{A}} < / div > < div > B: {{C}} < / div > < / div > < / template > < script >export default {
'name': 'bComp'.data() {
return {
'a': ' '.'c': ' '
};
},
'props': ['event'].mounted() {// pass$onTo listen on phone-a, phone-c event this.event.$on('phone-a', (a, num) => {
this.a = `${a}I am changing the value of num passed by the parent element:${num}`;
});
this.event.$on('phone-c', c => { this.c = c; }); }}; </script>Copy the code
The most important of these is that they must be in a common instance for the data to be passed to each other.
3. Provide/inject
Description:
The pair of options need to be used together, with the parent using provide to provide the data downward, and all the children below it can be injected via Inject. No matter how many generations are separated, multiple data supplied by different parents can be injected
- The provide option is an object or a function that returns an object. This object contains properties that can be injected into its descendants
- The Inject option is an array of strings, or an object
Usage:
// Parent <template> <div> <com-a></com-a>
</div>
</template>
<script>
import ComA from './a';
export default {
'name': 'home'.'components': {ComA},
provide() {
return {
'a': 'Hello'.'show': val => !val
};
}
};
</script>
Copy the code
// Child <template> <div> < el-button@click ="showFn(textShow)"<div v-if= </el-button> <div v-if="textShow"> I am a casual be manipulated text {{a}} < / div > < / div > < / template > < script >export default {
'name': 'ComA'.data() {
return {'textShow': true};
},
'inject': [
'a'.'show'].'methods': { showFn(val) { this.textShow = this.show(val); }}}; </script>Copy the code
If it is registered globally in the app.vue file (root), it can be referenced throughout the route (similar to global data management vuex).
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'.provide() {return {
app: this
}
}
}
</script>
Copy the code
Any component that then injects app can access all instances of app.vue directly through this.app.xx.
$parent / $children
Description:
$parent can be used to access an instance of the parent component from a child component. It provides an opportunity to reach the parent component at any time later, instead of passing data to the child component as a prop
<template>
<div class="b-content"> < div > I am a child component < / div > < span > {{msgText}} < / span > < / div > < / template > < script >export default {
'name': 'childComp'.data() {
return {
'msgText': ' '.'childMsg': 'Scream from child element'
};
},
created() {
this.msgText = this.$parent.parentMsg; // MsgText: from the parent component ha ha}}; </script>Copy the code
$Children can iterate through all child components. Note that $Children does not guarantee order and is not responsive.
<template>
<div class="b-content">< div> I am the parent component </div> <child-comp></child-comp> </div> </template> <script> import childComp from'./child';
export default {
'name': 'parentComp'.data() {
return {'parentMsg': 'Hehe from parent component'};
},
'components': {childComp},
mounted() {// Read the child component data, notice$childrenSorting of child components is not safe in console.log(this.$children[0].childMsg); // Shout from child element}}; </script>Copy the code
$root & refs
Description:
The $root attribute is in the child component of each new Vue instance, and its root instance is accessible through the $root attribute. For example, in this root instance:
// Vue root instance new Vue({data: {foo: 1}, computed: {bar:function() {/ *... */ } }, methods: { baz:function() {/ *... * /}}})Copy the code
All child components can access or use this instance as a global store.
// Get the root component's data this.$root.foo // Writes the root component's data this.$root.foo = 2 // Accesses the root component's calculated property this.$root.bar // Calls the root component's method this.$root.baz()
Copy the code
$refs property when you need to access a child component directly in JavaScript. You can assign an ID reference to a child component using the ref attribute. An object that holds all DOM elements and component instances for which the REF feature is registered. Such as:
<my-component ref="childrenCompA"></my-component>
Copy the code
Access the child component: this.$refs.childrenCompA
Copy the code
6, Vuex
For medium and large single-page applications, such as multi-user development and global maintenance of login status, we can choose VUEX for state management.
State is the data stored in vuex. By registering the Store option in the root instance, the store instance is injected into all the children of the root component, which can be accessed through this.$store.
When you need to fetch multiple data, you can do this:
import {mapState} from 'vuex'computed:{ ... mapState('commissionSetting'['listData'])},Copy the code
Not all states are suitable for vuEX, and some states belong to a single component, so it depends.
Mutations the only way to change the state in Vuex’s store is to submit mutation
const mutations = {
updateListData(state, payload){
state.listData = payload
}
}
Copy the code
Instead of calling updateListData directly, you need to call the store.mit method with the appropriate type:
store.commit('updateListData', data)
Copy the code
Actions commit mutations rather than directly changing the state. Actions can contain any asynchronous operation.
Write a simple action:
async getListAction({commit}, params){
const result = await getList(params)
const {code, message, data} = result
if(code === SUCCESS && data){// Commit change data commit('updateListData', data.rows)
}else{
vueInit.$Message.error({
content: message || 'Please try again later.'
});
}
return result
},
Copy the code
Vuex doesn’t limit your code structure. However, it lays down some rules that need to be followed:
- Application-level state should be centralized into a single Store object.
- Submitting mutation is the only way to change the state, and the process is synchronous.
- Asynchronous logic should be wrapped in actions.
As long as you follow these rules, you can organize your code any way you want. If your store file is too large, just split the action, mutation, and getter into separate files.
The last
Where there is life, there is learning. New knowledge points emerge in an endless stream, for us developers, the most important thing is to learn and can be applied to the actual project.