vue组件通讯的方式,并不局限于父子组件
适用于父子组件。
- 父组件向子组件传递 props 和事件
- 子组件接收 props ,使用 `this.$emit` 调用事件
直接代码是最方便的 每一步都有解释
--父组件
<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')//向父元素传递数据
}
},
}
通过 `this.$refs.xxx` 可以获取某个子组件,前提是子组件中要设置 `ref="xxx"`。
【注意 1】要在 `mounted` 中获取 `this.$refs`
【注意 2】在vue3中移除了$children 所以建议获取子组件的时候使用ref
父组件
<template>
<HelloWorld ref='helloWord' msg='传递给子组件的内容' @sayHi="sayHi"/>
</template>
mounted() {
console.log(this.$refs.helloWord) //这里就能够打印子组件所有的内容包括data和method 可以直接调用子组件中的方法
},
通过 `this.$parent` 可以获取父组件,并可以继续获取属性、调用方法等。
这个直接在子组件中调用即可,就不po代码了
适用于兄弟组件,或者是相差很远八杆子打不着的两个组件
这个分vue2和vue3 但是不管vue2还是vue3 都要记得销毁 区别就是vue2在beforeDestroy()中销毁 vue3在 beforeUnmount()中销毁
1-先说vue2
要注意引入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需要借助第三方库来实现自定义事件
这里我借助的是event-emitter (npm下载即可)
import ee from 'event-emitter'
const event = ee()
export default event
其他的与vue2一致 再次提醒!!在vue3中销毁是
beforeUnmount() {
event.off('onAddTitle', this.addTitleHandler)
},
$attrs存储是父组件中传递过来的,并且没有在 `props` 和 `emits` 中定义的属性和事件
相当于 props 和 emits 的一个补充
【注意】在props 和 emits中有的 就不会在this.$attrs中出现了
【注意】在vue2 的时候 事件会在$listener中获取 但是vue3移除了它,或者说是合并到了attrs中
另外假设我们是嵌套组件A套B B套C 如果c想要获取A的内容 就可以在B中 使用 v-bind=“$attrs” 这样C中可以获取到A和B所有没在props 和 emits 中的内容
组件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)
},
}
}
这个我个人认为是一个比较完美的能够用于多层嵌套组件的方案
只要在最上级provide一个属性 他的子孙们不管相隔多少层都可以获取到这个数据
【注意】vue2 和 vue3 写法有些许差异 在下面代码中显示了
【注意】上一层是否inject 都不影响本层组件获取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
vuex就是全局数据存储 之后会写一篇把之前总结在笔记里的内容分享给大家
(哈哈哈 一直拖着这个主要还是因为懒,因为分享就要写的能让大家看懂 自己整理只要自己看懂就好了)