How components communicate
- props
- $emit
- $listener and $attrs
- Global event bus
- vuex
props
Parent component
<template> <div> First <second :fatherMessage="fatherMessage" /> </div> </template> <script> import second from './Second' export default { name: 'First', data(){ return { fatherMessage:'come from first' } }, components: { second }, } </script>
Subcomponents
<template> <div> {{fatherMessage}} </div> </template> <script> export default { name: 'Second', props: { fatherMessage:{ type: String, default: '' } }, data(){ return {} } } </script>
effect
props can customize the authentication method:
-
Type: refers to the type of value. The following values are available:
String
Number
Boolean
Array
Object
Date
Function
Symbol
When there are multiple possible types, they can be passed through propA: [String, Number] -
Required: required
-
Default: the default value
The default value of an object or array needs to be obtained through a factory functionpropE: { type: Object, // Object or array defaults must be obtained from a factory function default: function () { return { message: 'hello' } } },
Allow custom functions to validate
propE: { validator: function (value) { // This value must match one of the following strings return ['success', 'warning', 'danger'].indexOf(value) !== -1 } }
prop has a one-way data flow, that is, the child component cannot modify the value passed in by the parent component.
$emit
Subcomponents
<template> <div> <button @click="sendMsgToFirst">towards First send message</button> </div> </template> <script> export default { name: 'Second', data(){ return {} }, methods: { sendMsgToFirst(){ this.$emit('getMsgFromSecond','msg from second') } } } </script>
Parent component
<template> <div> First <second v-on:getMsgFromSecond="getMsgFromSecond"/> </div> </template> <script> import second from './Second' export default { name: 'First', data(){ return { fatherMessage:'come from first' } }, components: { second }, methods: { getMsgFromSecond(val){ console.log(val); } } } </script>
effect
This method is used for vue instances and is limited to the child component passing values to the parent component
$listener and $attrs
Sun Tzu (and below) components
<template> <div> adasd </div> </template> <script> export default { name: 'Third', data(){ return {} }, components: { }, mounted(){ console.log('this.$attrs',this.$attrs); console.log('this.$listeners',this.$listeners); this.$listeners.eventFromFirst() } } </script>
Subcomponents
<template> <div> second <third v-bind="$attrs" v-on="$listeners"/> </div> </template> <script> import third from './Third' export default { name: 'Second', data(){ return {} }, components: { third }, methods: { } } </script>
Parent component
<template> <div> First <second :msgFromFirst="msgFromFirst" @eventFromFirst="eventFromFirst"/> </div> </template> <script> import second from './Second' export default { name: 'First', data(){ return { msgFromFirst:'come from first' } }, components: { second }, methods: { eventFromFirst(){ console.log('a event from first'); } } } </script>
effect
This method is more suitable for multi-component communication than prop. At the same time, as long as we receive an attribute in the sub component, the attribute will be "truncated" by the sub component, and the grandchildren will not be able to get it.
In official terms, that is:
$attribs contains attribute bindings (except class and style) in the parent scope that are not recognized (and obtained) as props. When a component does not declare any prop, all parent scope bindings (except class and style) will be included here, and internal components can be passed in through v-bind="$attrs" - very useful when creating high-level components.
For $listeners
Contains v-on event listeners in the parent scope (without. native modifiers). It can pass in internal components through v-on="$listeners" - very useful when creating higher-level components.
Global event bus
main.js
new Vue({ ...... beforeCreate(){ Vue.prototype.$bus = this // Install the global event bus, $bus is the vue of the current application } ...... })
Component A
<template> <div> First <second/> </div> </template> <script> import second from './Second' export default { name: 'First', data(){ return { } }, components: { second }, methods: { }, mounted(){ this.$bus.$emit('globalEvent','a msg from first') } } </script>
Component B (mainly indicating that C and A are not parent-child relationships)
<template> <div> second <third/> </div> </template> <script> import third from './Third' export default { name: 'Second', data(){ return {} }, components: { third }, methods: { } } </script>
Component C
<template> <div> third </div> </template> <script> export default { name: 'Third', data(){ return {} }, components: { }, mounted(){ this.$bus.$on('globalEvent',(val)=>{ console.log('this is third >>>',val); }) } } </script>
effect
This method can communicate with any component, but you should pay attention to registering events after the component is created and unbinding through $off after the component is destroyed
Vuex
If the business logic is complex and many components need to process some public data at the same time, the above methods may not be conducive to project maintenance. vuex's approach is to extract these public data, and then other components can read and write these public data, so as to achieve the purpose of understanding coupling.
See the document for details: https://vuex.vuejs.org/zh/