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. Referencesrefandchildren

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.