前言
在vue组件开发(一)中介绍了父子组件之间的通讯,除父子组件之间通讯外,还有兄弟组件之间的通讯,所谓的兄弟组件是指在同一组件中同时使用A和B两个兄弟组件,点击子组件A需要另一子组件B响应,则组件A和组件B为兄弟组件。兄弟组件之间的通讯也是vue组件开发中常见的通讯方式之一。为了解决兄弟组件之间的耦合,一般采用公共耦合方式,即通过第三方的方式进行间接耦合,如下图所示
此种通讯方式类似设计模式中的中介者模式,eventBus、vuex类似中介者,各个组件彼此并不直接耦合,确保每个组件的独立性和复用性。VUE开发兄弟组件之间的通讯,小项目一般使用eventBus,大项目多使用 vuex。
eventBus
EventBus 又称为事件总线,使用 EventBus 来作为沟通桥梁的概念,是所有组件共用相同的事件中心,各个组件可以向该中心注册发送事件和接收事件。在vue中EventBus存在形式就是一个独立的.js文件。
【例】 组件A,组件B之间通过eventbus进行通讯,当点击组件上按钮时,将B组件的msg值发送给A组件显示
- 创建一个bus.js文件,充当eventbus容器,代码如下:
import Vue from 'vue';
export default new Vue
- 定义组件ChildA,用于接收数据组件,通过eventbus监听ChildB中的“clickBtn”的事件,其代码如下
<template>
<div>
<span>{{msg}}</span>
</br>
<span>B组件发送的消息为:{{recMsg}}</span>
</div>
</template>
<script>
import eventBus from '../utils/Bus.js' //引入bus.js
export default {
name: 'v-childA',
data() {
return {
msg: '这是A组件消息',
recMsg: 'www'
}
},
mounted: function() {
var that = this;
//注意:clickBtn是发送和监听的事件名称,target就是获取的数据形参,叫什么都可以(当然了,这一定要符合形参变量的命名规范)
eventBus.$on('clickBtn', target => {
that.recMsg = target;
console.log(target);
});
}
}
</script>
这里需要提醒的是监听事件需要放置在mounted或create中。
3) 定义组件ChildB,通过eventbus发送ChildB中的“clickBtn”的事件,告知监听者更新数据,其代码如下
<template>
<div>
<input type="button" v-on:click="addCart" value="请查看控制台" />
</div>
</template>
<script>
import eventBus from '../utils/Bus.js' //引入bus.js
export default {
name:'v-childB',
data() {
return {
msg: '这是B组件发送的消息'
}
},
methods: {
addCart(event) {
// 这个clickBtn是一个自定义的事件名称,this.msg就是你要传递的数据。
eventBus.$emit('clickBtn',this.msg);
}
}
}
</script>
- 测试,创建父组件,父组件包括v-childA、v-childB两个组件,点击B组件按钮,在A组件显示B组件传递消息,其代码如下
<template>
<div>
<v-childA></v-childA>
<v-childB></v-childB>
</div>
</template>
<script>
import v-childA from '../components/ v-childA
import v-childB from '../components/ v-childB
export default {
name: "test-event",
components: {
v-childA,
v-childB
}
}
</script>
运行结果如下:
点击B组件上按钮,将B组件中的数据msg交给A组件显示。
实际上eventBus在设计模式中就是观察者模式一种典型的应用,一个或多个组件将监听事件注册到eventBus中,另外一个组件在触发该事件,将消息进行发布。
【注】:用bus 来进行页面组件之间的数据传递,需要注意两点,组件v-ChildB的
e
m
i
t
事
件
应
在
b
e
f
o
r
e
D
e
s
t
o
r
y
生
命
周
期
内
。
其
次
,
组
件
v
−
c
h
i
l
d
A
内
的
emit事件应在beforeDestory生命周期内。其次,组件v-childA内的
emit事件应在beforeDestory生命周期内。其次,组件v−childA内的on要销毁,一般放在beforeDestroy()和destroyed()事件中,使用语法为eventBus.$off(‘clickBtn’)参数为监听事件的名称
vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用所有组件的状态。Vuex 实现了一个单向数据流,在全局拥有一个 State 存放数据,当组件要更改 State 中的数据时,必须通过 Mutation 进行,Mutation 同时提供了订阅者模式供外部插件调用获取 State 数据的更新。如:A组件更改了state中的msg,B、C两个组件在使用msg,VUEX通过Mutation通知B、C组件修改其状态。VUEX比较复杂,在后续章节再做介绍。
sessionStorage和localStorage
vuex存储数据是在内存中,刷新页面数据就会丢失,在一些处理场景,需要长期记录获取的数据,如:登录信息、token信息,提供所有组件使用。解决办法是将state的数据保存在localstorage、sessionstorage或者cookies中,由于cookies的安全性,现在几乎不再使用。此时。组件A将要通讯的数据以数据对象形式写入sessionStorage或localstorage,B组件通过读取存入数据对象实现A、B组件之间的通讯。
localstorage和sessionStorage使用key和value进行存储。存入代码如下
//单值存储
sessionStorage. setItem(‘key’,value)
//value值必须为字符串,不为字符串会自动转换成字符串
//对象存储
var orderData = { 'orderId': 123, 'price': 88 }
sessionStorage.setItem('缓存名称', JSON.stringify(orderData))
//存储值:将对象转换为Json字符串
获取一般采用getItem(key) 方法获取数据,代码如下
//单数据读取,获取key对应的value
sessionStorage.getItem('Key')
//对象读取:需要通过JSON.parse()将文本转换为对象
var userJsonStr = sessionStorage.getItem('key');
userEntity = JSON.parse(userJsonStr);
总结
兄弟组件之间主要通过bus、vuex进行通讯,对于需要全局共享的数据使用,则使用localstorage和sessionStorage来完成。在组件化开发中还可以通过路由传参及插槽完成组件间的通讯。