总结:Vue组件间的通信
一、父子组件
1、父组件传值属性传参,子组件
props
接收
例:
父组件:
<div>
<child val="val"></child>
</div>
子组件:
<script>
export default {
props: {
val: {
type: String,
default: ''
}
}
}
</script>
2、
$attrs
接收父组件传值,但没有在子组件props声明
例:
父组件:
<div>
<child val="val"></child>
</div>
子组件:
<div>
<div v-bind="$attrs" :val="$attrs.val"></div>
</div>
注意
:
v-bind="$attrs"
此种方式
$attrs
会以键值对的形式默认展开在当前节点,但是当前实例的根节点会继承
$attrs
展开的属性
解决:
export default {
inheritAttrs: false
}
3、
$refs
父组件获取子组件实例从而修改子组件的数据
例:
父组件:
<div>
<child ref="child"></child>
</div>
export default {
mounted () {
this.$refs.child.val = '111111111111'
}
}
子组件:
export default {
data() {
return {
val: '1'
}
}
}
4、
$children
父组件获取子组件实例从而修改子组件的数据
父组件:
<div>
<child></child>
</div>
export default {
mounted () {
this.$children[0].val = '111111111111'
}
}
子组件:
export default {
data() {
return {
val: '1'
}
}
}
注意
:此种方式不推荐使用,因为父组件内可能会有很多子组件,并且子组件有可能是为异步组件,所以父组件内各个子组件实例的顺序即
index
下标并不一定是固定的,所以有可能会导致获取改变失败。
5、
$emit
子组件派发事件,父组件内的子组件监听事件(事件由派发者监听)
子组件:
<div>
<button @click="clickBtn">点击派发事件</button>
</div>
export default {
methods () {
clickBtn () {
this.$emit('myClick', '子组件内部点击触发')
}
}
}
父组件:
<div>
<child @myClick="myClick"></child>
</div>
export default {
methods () {
myClick (val) {
console.log(val) // 子组件内部点击触发
}
}
}
注意
: 常用此种方式进行子组件向父组件的通信
二、兄弟组件之间的通信
注意:兄弟组件间的通信通常会使用第三方传递,即兄弟组件共同的父辈或者祖辈来传递数据
注意:兄弟组件间的通信通常会使用第三方传递,即兄弟组件共同的父辈或者祖辈来传递数据
例
父辈组件:$parent || $root
<div>
<child1></child1>
<child2></child2>
</div>
子组件1:子组件1点击触发通讯给子组件2
<div>
<div @click="say2"></div>
</div>
export default {
methods () {
say2 () {
this.$parent.$emit('receice1')
}
}
}
子组件2:子组件2内部监听子组件1触发的通信
export default {
mounted () {
this.$parent.$on('receive1', () => {
console.log('我接收到了来自兄弟的通信')
})
}
}
三、祖先和后代间的通信(跨很多组件) provide
、 inject
provide
inject
正常很少使用这种方式,组件开发的时候偶尔会用到
正常很少使用这种方式,组件开发的时候偶尔会用到
例
祖先节点:
export default {
provide () {
return {
val: 111
}
}
}
后代节点:
export default {
inject: [
'val'
]
}
注意:单向传递数据(由祖先-》后代)
四、任意两个组件间的通信 vuex
、事件总线 bus
vuex
bus
1、
vuex
采用最多的一种方式,不做示例
2、事件总线
bus
:
抽离出
bus
bus.js
import Vue from 'vue'
const Bus = new Vue()
export default Bus
使用
bus
import Bus from './utils/bus'
Bus.$emit('busHandle')
Bus.$on('busHandle', () => {})
注意
:注册的总线事件要在组件销毁时卸载,否则会多次挂载,造成触发一次但多个响应的情况
export default {
beforeDestroy () {
this.bus.$off('busHandle')
}
}
模拟
BUS
的实现
// bus.js
class Bus {
constructor: {
this.classback = {} // 用来存储所有的事件
}
$on (name, fn) { // name:事件名形参名,fn为事件回调函数
this.callback[name] = this.callback[name] || [] // 当name第一次被监听,则创建一个名为name的数组,用来存储所有的该name的回调函数
this.callback[name].push(fn)
}
$emit (name, args) { // name、args触发回调函数传递的参数
if (this.callback[name]) {
this.callback[name].forEach((cb) => {
cb(args) // 触发当前name身上绑定的所有的回调函数
})
}
}
}
export default Bus
使用:引入
bus
(
bus.$on
、
bus.$emit
)