本文已参与[新人创作礼]活动,一起开启掘金创作之路。
事件总线
父组件->子组件:使用props。
子组件->父组件:使用$emit。
事件总线可以用在任意组件之间传值。
事件总线就是在接收数据的组件接收绑定事件的回调,在发送数据的组件触发事件并带值。其中借助了一个中间属性,把事件放在中间属性上面。
中间属性的特点:
1.全部组件都能看见。
2.能调用off、$emit,对事件进行操作。
为了满足以上两点,需要操作Vue的原型对象,修改main.js文件:
安装全局总线事件:
main.js
...
new Vue({
...
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
},
...
}).$mount('#app')
接收数据的组件监听事件:
oneComponent.vue
<template>
<div>
<span>这是组件A,接收B组件传值。{{ myData }}</span>
</div>
</template>
<script>
export default {
name: "oneComponent",
data() {
return {
myData: {},
};
},
methods: {
listOne(data) {
this.myData = data;
console.log(data);
},
},
mounted() {
// 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
// this.$bus.$on("事件名", 事件回调);
this.$bus.$on("eventName", this.listOne);
},
// 当组件销毁时,最好解绑用到的事件。
beforeDestroy() {
this.$bus.$off("eventName");
},
};
</script>
<style lang="less">
</style>
在接收时,也可以使用箭头函数去接收:
...
mounted() {
// 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
// this.$bus.$on("事件名", 事件回调);
this.$bus.$on("eventName", (data) => {
this.myData = data;
console.log(data);
});
},
...
发送数据的组件触发事件:
twoComponent.vue
<template>
<div>
这是组件B
<button type="primary" @click="updateData">给组件A传值</button>
</div>
</template>
<script>
export default {
name: "twoComponent",
data() {
return {
list: {
value: "value1",
type: "type1",
},
};
},
methods: {
updateData() {
// 触发事件,并传值
this.$bus.$emit("eventName", this.list);
}
},
};
</script>
<style lang="less">
</style>
组件使用:
<template>
<div>
<one-component></one-component>
<span>----------------</span>
<two-component></two-component>
</div>
</template>
<script>
import oneComponent from '@/components/oneComponent'
import twoComponent from '@/components/twoComponent'
export default {
...
components: { oneComponent,twoComponent },
...
}
</script>
<style lang="less">
</style>
注意:刚开始理解成了,可以先在B页面触发即$emit,再切换A页面看是否收到了数据($on是放在mounted里面的)。这样只有切换到A页面,才能调用$on,所以这一流程的执行顺序为先$bus.$emit,再$bus.$on。这样一直没有收到数据,这个理解是错误的。
触发后再绑定事件自然就不会接收已结束的事件了,$on就监听不到触发的事件,所以需要现有$on的存在,才能接收$emit触发事件所传过去的值。
事件应该是先注册($on)而后才能去触发($emit)。
监听事件时,只要有组件触发事件就能接收到数据。
接收数据的注册事件,事件的回调留在该组件,发送数据的组件触发事件,传递数据。
消息订阅与发布
消息订阅与发布也是实现组件间任意通信的方法。
先订阅(接收数据的订阅)-再发布(发送数据的发布)
这里需要安装库,有很多种,这里使用pubsub-js
先安装库:
npm install pubsub-js
在使用的组件中引入,引入的是一个对象,里面有很多方法。
接收消息的组件订阅消息:
oneComponent.vue
<template>
<div>
<span>这是组件A,接收B组件传值。{{ myData }}</span>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: "oneComponent",
data() {
return {
myData: {},
};
},
methods: {
},
mounted() {
// 订阅消息,只要有组件发布消息,就能接收到数据。
this.pubId = pubsub.subscribe("msgName", (msgName,data) => {
this.myData = data;
console.log(msgName);
console.log(data);
});
},
// 当组件销毁时,取消订阅。
beforeDestroy() {
pubsub.unsubscribe(this.pubId);
},
};
</script>
<style lang="less">
</style>
发送消息的组件发布消息:
twoComponent.vue
<template>
<div>
这是组件B
<button type="primary" @click="updateData">给组件A传值</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: "twoComponent",
data() {
return {
list: {
value: "value1",
type: "type1",
},
};
},
methods: {
updateData() {
// 发布消息
pubsub.publish("msgName", this.list);
}
},
};
</script>
<style lang="less">
</style>