From: 8 component communication methods in VUE, worth collecting!

1.props / $emit

The parent component passes data to the child component via props, while the $EMIT child component communicates to the parent.

① Parent component passes value to child component

Articles :[‘ DREAM of red Mansions ‘,’ Journey to the West ‘,’ Romance of The Three Kingdoms ‘]

// section parent component
<template>
  <div class="section">
    <com-article :articles="articleList"></com-article>
  </div>
</template>

<script>
import comArticle from './test/article.vue'
export default {
  name: 'HelloWorld'.components: { comArticle },
  data() {
    return {
      articleList: [A Dream of Red Mansions.Journey to the West.Romance of The Three Kingdoms]}}}</script>
Copy the code
// Child component article.vue
<template>
  <div>
    <span v-for="(item, index) in articles" :key="index">{{item}}</span>
  </div>
</template>

<script>
export default {
  props: ['articles']}</script>
Copy the code

② The child component passes values to the parent component

$EMIT binds a custom event. When the statement is executed, the arG parameter is passed to the parent component, which listens and receives the parameter via V-ON.

$emit(‘onEmitIndex’, index) $emit(‘onEmitIndex’, index) $emit(‘onEmitIndex’, index)

// In the parent component
<template>
  <div class="section">
    <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
    <p>{{currentIndex}}</p>
  </div>
</template>
<script>
import comArticle from './test/article.vue'
export default {
  name: 'HelloWorld'.components: { comArticle },
  data() {
    return {
      currentIndex: -1.articleList: [A Dream of Red Mansions.Journey to the West.Romance of The Three Kingdoms]}},methods: {
    onEmitIndex(idx) {
      this.currentIndex = idx
    }
  }
}
</script>
Copy the code
/ / child component
<template>
  <div>
    <div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</div>
  </div>
</template>
<script>
export default {
  props: ['articles'].methods: {
    emitIndex(index) {
      this.$emit('onEmitIndex', index)
    }
  }
}
</script>
Copy the code

2.$children / $parent

(1) the parent component$parent

this.$children[0].messageA = 'this is new value'

// In the parent component
<template>
  <div class="hello_world">
    <div>{{msg}}</div>
    <com-a></com-a>
    <button @click="changeA">Click Change child component values</button>
  </div>
</template>
<script>
import ComA from './test/comA.vue'
export default {
  name: 'HelloWorld'.components: { ComA },
  data() {
    return {
      msg: 'Welcome'}},methods: {
    changeA() {
      // Get the child component A
      this.$children[0].messageA = 'this is new value'}}}</script>
Copy the code

(2) the child components$parent

this.$parent.msg

// In the child component
<template>
  <div class="com_a">
    <span>{{messageA}}</span>
    <p>Get the value of the parent component: {{parentVal}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      messageA: 'this is old'}},computed: {parentVal(){
      return this.$parent.msg; }}}</script>
Copy the code

3.provide/ inject

Provide/Inject is a new API in Vue2.2.0. Simply put, provide variables in the parent component and inject variables in the child component.

Let’s use an example to verify the above description: Suppose there are three components: A.vue, B.vue, and C. Vue, where C is A child of B, and B is A child of A, and A>>B>>C

Parent component provide sends down data (provide: {for: “demo”}), child component use inject (inject: [‘for’])

// A.vue
<template>
  <div>
	<comB></comB>
  </div>
</template>

<script>
  import comB from '.. /components/test/comB.vue'
  export default {
    name: "A".provide: {
      for: "demo"
    },
    components:{
      comB
    }
  }
</script>
Copy the code
// B.vue
<template>
  <div>
    {{demo}}
    <comC></comC>
  </div>
</template>

<script>
  import comC from '.. /components/test/comC.vue'
  export default {
    name: "B".inject: ['for'].data() {
      return {
        demo: this.for
      }
    },
    components: {
      comC
    }
  }
</script>
Copy the code
// C.vue
<template>
  <div>
    {{demo}}
  </div>
</template>

<script>
  export default {
    name: "C".inject: ['for'].data() {
      return {
        demo: this.for
      }
    }
  }
</script>
Copy the code

4.ref / refs

Ref: If used on a normal DOM element, the reference refers to the DOM element; When used on a child component, the reference refers to the component instance, through which you can directly invoke the component’s methods or access data

// Subcomponent a.ue
export default {
  data () {
    return {
      name: 'Vue.js'}},methods: {
    sayHello () {
      console.log('hello')}}}Copy the code
// Parent component app.vue
<template>
  <component-a ref="comA"></component-a>
</template>
<script>
  export default {
    mounted () {
      const comA = this.$refs.comA;
      console.log(comA.name);  // Vue.js
      comA.sayHello();  // hello}}</script>
Copy the code

5.evnetBus

EventBus, also known as the eventBus, can be used in vue as a bridge concept, as all components share the same event center to which they can register to send and receive events, so that components can notify other components.

EventBus also has its drawbacks. When a project is large, it can be a disaster that is difficult to maintain

(1) the initialization

You first need to create an event bus and export it so that other modules can use it or listen on it.

// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
Copy the code

② Send event

// addtionNum. Vue sends events
<template>
  <div>
    <button @click="additionHandle">+ adder</button>    
  </div>
</template>

<script>
import {EventBus} from './event-bus.js'
console.log(EventBus)
export default {
  data(){
    return{
      num:1}},methods: {additionHandle(){
      EventBus.$emit('addition', {
        num:this.num++
      })
    }
  }
}
</script>
Copy the code

③ Receiving events

// events are received in shownum. vue

<template>
  <div>Count and: {{count}}</div>
</template>
<script>
import { EventBus } from './event-bus.js'
export default {
  data() {
    return {
      count: 0}},mounted() {
    EventBus.$on('addition'.param= > {
      this.count = this.count + param.num; }}})</script>
Copy the code

This makes it possible to click the add button in the component addtionNum. Vue and display the sum with the num passed in showNum. Vue.

(4) Remove event listeners

import { eventBus } from 'event-bus.js'
EventBus.$off('addition', {})
Copy the code

6.VueX

Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way. Vuex solves the problem of multiple views relying on the same state and behavior from different views needing to change the same state, focusing developers’ efforts on updating data rather than transferring data between components.

① Storing data

 this.$store.commit('receiveBMsg', {
          BMsg: this.BMessage
        })
Copy the code

② Reading data

this.$store.state.BMsg
Copy the code

7.localStorage / sessionStorage

  • throughwindow.localStorage.getItem(key)To get the data
  • throughwindow.localStorage.setItem(key,value)Store the data

8.$attrswith$listeners

vm.$attrs

Contains attribute bindings (except class and style) that are not recognized (and retrieved) as prop in the parent scope. When a component does not declare any prop, all parent-scoped bindings (except class and style) are included, and internal components can be passed in via V-bind =”$attrs” — useful when creating higher-level components.

vm.$listeners

Contains v-ON event listeners in the parent scope (without the.native modifier). Internal components can be passed in via V-on =”$Listeners “– useful for creating higher-level components.

example

// app.vue
// index.vue
<template>
  <div>
    <child-com1
      :name="name"
      :age="age"
      :gender="gender"
      :height="height"
      title="Programmer growth is north."
    ></child-com1>
  </div>
</template>
<script>
const childCom1 = () = > import("./childCom1.vue");
export default {
  components: { childCom1 },
  data() {
    return {
      name: "zhang".age: "18".gender: "Female".height: "158"}; }};</script>
Copy the code
// childCom1.vue
<template class="border">
  <div>
    <p>name: {{ name}}</p>
    <p>ChildCom1 $attrs: {{$attrs}}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
const childCom2 = () = > import("./childCom2.vue");
export default {
  components: {
    childCom2
  },
  inheritAttrs: false.// You can turn off properties that are not declared in props that are automatically mounted to component root elements
  props: {
    name: String // Name is bound as the props property
  },
  created() {
    console.log(this.$attrs);
     / / {" age ", "18", "gender" : "female" and "height" : "158", "title" : "programmers growth refers to the north"}}};</script>
Copy the code
// childCom2.vue

<template>
  <div class="border">
    <p>age: {{ age}}</p>
    <p>childCom2: {{ $attrs }}</p>
  </div>
</template>
<script>

export default {
  inheritAttrs: false.props: {
    age: String
  },
  created() {
    console.log(this.$attrs); 
    / / {" gender ":" female "and" height ":" 158 ", "title" : "programmers growth refers to the north"}}};</script>
Copy the code

conclusion

  • Parent-child component communication:props; $parent/ $children; provide / inject ; ref ; $attrs / $listeners
  • Sibling communication:eventBus ; vuex
  • Cross-level communication:eventBus;Vuex;provide / inject$attrs / $listeners