Summary of component communication methods

Posted by Ghost_81st on Sun, 24 Oct 2021 11:16:05 +0200

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 function

    propE: {
      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/

Topics: Vue