Compared to the concept of React controlled components, the “communication” between Vue components is much stronger.
This “communication” feature is reflected in the fact that the component has its own state management inside, and only behaves as the transfer of information externally, without the need for external components to make any special behavior (for example, the state of the controlled component is completely determined by the controller, and the controller must respond to the change of the state of the controlled component).
In addition to the usual parent-child level communication, there are sibling, cross-level, to bus, and Vuex. It has to be said that Vue components communicate in a richer way.
The parent component passes messages to the child component
1. The attributeprops
The most basic form of father-son transmission.
// child specifies props
export default {
props: {
msg: String}}// parent passes the message
<child msg='msg' />
Copy the code
2. Referencesref
andchildren
Gets the child component reference directly to set the internal value of the child component. Children is an array that holds all the custom child components, but the order is not guaranteed in the case of multiple child components. So it is more reliable that the child sets the ref and the parent uses $refs to get the child reference.
// child
export default {
data() {
return {
// parent msg by $refs
// or
// parent msg by $children
current: ' '}}}// parent
<child ref="child">
export default {
methods: {
handleChange1() {
this.$refs.child.current = 'parent msg by $refs'
},
handleChange2() {
this.$children[0].current = 'parent msg by $children'}},mounted() {
// this.handleChange1()
// or
// this.handleChange2() }}Copy the code
Child components pass messages to parent components
1. Customize events
The core means of sending messages up
// child
<button @click="sendMsg" />
export default {
methods: {
sendMsg() {
this.$emit('sendMsg', { msg: 'msg'})}}}// parent
<child @send-msg="receiveMsg" />
export default {
methods: {
receiveMsg(param) {
console.log(param) // { msg: 'msg' } }}}Copy the code
The essence of v-model and.sync is also a combination of props➕ custom events
Ancestor components pass messages to descendant components
Characteristics of 1.$attr
Pass values that are not set in the props component. Often use inheritAttrs: false in the props component to uninherit non-props values on the root component. But $attrs is unique in that it can pass information all the way back in the “family tree” : each member can pass an ancestor’s non-props attribute using v-bind=”$attrs”.
// grandson
export default {
mounted() {
console.log(this.$attrs.attr) // attr}}// child
<grandson v-bing="$attrs" />
export default {
props: {
msg: String
},
mounted() {
console.log(this.msg, this.$attrs.attr) // props, attr}}// Parent passes props and attrs messages
<child msg="prop" attr="attr" />
Copy the code
2. Provide and injectprovide
/inject
The means by which one ancestor provides information to all generations need not be transmitted by each generation
// grandson
export default {
inject: ['msg'].mounted() {
console.log(this.msg) // 'msg'}}// child
<grandson />
// parent
<child />
export default {
provide() {
return {
msg: 'msg'}}}Copy the code
Descendant components pass messages to ancestor components
1. The listener$listeners
$Listeners can relay events backwards (normal and custom), triggering events by a descendant to send messages to ancestors
// grandson
<button @click="sendMsg"</button> Trigger ancestor custom eventexport default {
methods: {
sendMsg() {
this.$listeners['on-send'] ({grandson: 'grandson'})}}}// child
<grandson v-on="$listeners"/>
// parent
<child @on-send="receiveMsg" />
export default {
methods: {
receiveMsg(param) {
console.log(param) // { grandson: 'grandson' }}}}Copy the code
Sibling components send messages
1. Use a common father or ancestor
// brother-send
export default {
mounted() {
this.$parent.$emit('parent-msg', { msg: 'msg by parent' })
this.$root.$emit('root-msg', { msg: 'msg by root'}}})// brother-receive
export default {
created() {
this.$parent.$on('parent-msg'.(param) = > {
console.log(param) // { msg: 'msg by parent' }
})
this.$root.$on('root-msg'.(param) = > {
console.log(param) // { msg: 'msg by root' }})},destroyed() {
this.$parent.$off('parent-msg')
this.$root.$off('root-msg')}}// parent
<div>
<brother-send />
<brother-receive />
</div>
Copy the code
Irregular cross – level communication
1. Event Bus
You can use an empty Vue object with the $ON $EMIT $OFF API
// bus.js
export default new Vue()
Copy the code
You can also build your own
// bus.js
class Bus {
constructor() {
this.callbacks = {}
}
$on(name, fn) {
this.callbacks[name] = this.callbacks[name] || []
this.callbacks[name].push(fn) } $emit(name, ... args) {if (this.callbacks[name]) {
this.callbacks[name].forEach(cb= >cb(... args)) } } $off(name) {this.callbacks[name] = null
Reflect.deleteProperty(this.callbacks, name)
}
}
export default new Bus()
Copy the code
State management
Vuex
Vuex solves all communication problems between components, but in reality Vuex is more of a “library” for state management. Vuex is relatively heavy, but holds all required data structures and is accessible to all components. Again, Vuex depends on the project size, or data size.