[vue] How vue components communicate (vue2+vue3)

The way Vue components communicate is not limited to parent-child components

1: props and $emit

Applies to parent-child components.

- Parent component passes props and events to child components

- Child components receive props and use `this.$emit` to call events

Direct code is most convenient with explanations at every step

--父组件
    <HelloWorld msg='传递给子组件的内容' @sayHi="sayHi"/>//当子元素emit'sayHi'的时候会调用父元素中的sayHi方法

  
methods: {
    sayHi(msg) {//收到子元素传递来的数据
      console.log(msg);//Hi
    }
  }

--子组件
<template>
  <h1 @click="clickHandler">{
   
   { msg }}</h1>
</template>

export default {
  props: { //接受父元素传来的数据
    msg: String
  },
 emits: ['showMsg'], // Vue3 如果是vue2不需要写emits
  methods: {
    clickHandler() {
      this.$emit('sayHi', 'Hi')//向父元素传递数据
    }
  },
}

Two: $refs

A certain subcomponent can be obtained through `this.$refs.xxx`, provided that `ref="xxx"` is set in the subcomponent.

[Note 1] Get `this.$refs` in `mounted` 

[Note 2] $children has been removed in vue3, so it is recommended to use ref when obtaining child components.

父组件
<template>
    <HelloWorld ref='helloWord' msg='传递给子组件的内容' @sayHi="sayHi"/>

</template>

 mounted() {
    console.log(this.$refs.helloWord) //这里就能够打印子组件所有的内容包括data和method 可以直接调用子组件中的方法
  },

Three: $parent

You can get the parent component through `this.$parent`, and you can continue to get properties, call methods, etc.

This can be called directly in the subcomponent, and there is no need to post the code.

Four: Custom events

Suitable for brother components, or two components that are far apart and cannot be hit with eight poles.

This is divided into vue2 and vue3, but no matter vue2 or vue3, you must remember to destroy it. The difference is that vue2 is destroyed in beforeDestroy() and vue3 is destroyed in beforeUnmount().

1-Let’s talk about vue2 first

要注意引入event
event.js
import Vue from 'vue'
export default new Vue() //其实就是个vue实例 你要是不嫌弃麻烦愿意每次都event也不是不可以


----A组件

import event from './event'


 mounted() {

     addTitleHandler(title) {
            console.log('on add title', title)
        }
      // 绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler)//addTitleHandler是事件名字
     },

  
   beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler)
    }   
  
----B组件  
  methods: {
        addTitle() {
            // 调用自定义事件
            event.$emit('onAddTitle', this.title)
            this.title = ''
        }
    } 

2-vue3 requires the use of third-party libraries to implement custom events

Here I use event-emitter (just download it from npm)

import ee from 'event-emitter'


const event = ee()

export default event

其他的与vue2一致 再次提醒!!在vue3中销毁是

  beforeUnmount() {
    event.off('onAddTitle', this.addTitleHandler)
  },

Five: $attr

The $attrs storage is passed from the parent component, and there are no properties and events defined in `props` and `emits`

Equivalent to a supplement to props and emits

[Note] Some props and emits will not appear in this.$attrs.

[Note] In vue2, the event will be obtained in $listener, but vue3 removes it, or merges it into attrs.

In addition, suppose we have nested components A, BB, and C. If c wants to get the content of A, it can use v-bind="$attrs" in B. In this way, C can get all the props and emits of A and B. Content

组件A
<template>
    <p>A <input v-model="name"></p>

    <B
        :a="a"
        :b="b"
        @getA="getA" 
        @getB="getB"
        
    ></B>
</template>

组件B
<template>
    <p>B <input v-model="name"></p>

    <C
        :y="y"
        :z="z"
        @getZ="getZ"
        @getY="getY"
        v-bind="$attrs"//相当于把B获取到的attrs全部传递给了c
    ></C>
</template>

export default {

    props: ['a'],
    emits: ['getA'],
    data() {
        return {
            y: 'yyy',
            z: 'zzz'
        }
    },
 created() {
//可以获取到b和getb 因为他们没有在props和emit里
         console.log(this.$attrs)  
    },
    methods: {
  
        getY() {
            return this.y
        },
        getZ() {
            return this.z
        }
    },
   
}

组件C
export default {

    props: ['y'],
    emits: ['getY'], 
    created() {
 //可以获取到b,z和getb getz 因为他们没有在props和emit里 
//获取到b和getb是因v-bind如果没有写这个属性 只会获取到B组件传来的不再props和emit中的数据和方法
         console.log(this.$attrs) 
    },
   }
    
   
}

Six: provide/inject

I personally think this is a relatively perfect solution that can be used for multi-layer nested components.

As long as an attribute is provided at the top level, its descendants can obtain this data no matter how many layers apart they are.

[Note] There are slight differences in the writing methods of vue2 and vue3, which are shown in the following code.

[Note] Whether the upper layer is injected or not does not affect the component of this layer to obtain provide.

组件A
<template>
    <p>A <input v-model="name"></p>
    <B></B>
</template>

import { computed } from 'vue'

export default {
    data() {
        return {
            a:'aa',
        }
    },
    //传递一个静态数据 vue2 和 vue3 写法一致
    // provide: {
    //     info: 'aaa' 
    // }

    //vue2传递data中的数据
    provide() {
        return {
            info:this.a
        }
    }

    //vue3传递data中的数据
    provide() {
        return {
            info: computed(() => this.a)
        }
    }
}

组件B
<template>
    <p>{
   
   {info}}</p> //可以在这里直接使用

    <C></C>
</template>

export default {

   inject: ['info'] //获取到info
   
}

组件C 同理 无论组件B是否使用inject 都不影响C


Seven: vuex

Vuex is the global data storage. I will write an article later to share with everyone the content summarized in the notes.
(Hahaha, I have been putting this off mainly because of laziness, because sharing must be written so that everyone can understand it. I can organize it and understand it by myself. Enough)

Guess you like

Origin blog.csdn.net/wuguidian1114/article/details/123259094