Когда я раньше видел публикацию и подписку , я всегда думал, что это фиксированный код и какой-то алгоритм. Недавно я узнал о принципе отзывчивости Vue и, кстати, взглянул на него. Только чтобы узнать, что это всего лишь дизайнерская идея, запишите ее перед запуском.
1. Инкапсулируйте класс PubSub
PubSub.js
class PubSub {
constructor() {
this.subs = {
}; // 存储自定义事件
}
subscribe(type, fn) {
//订阅 type是任务队列的类型 ,fn是方法
if (!this.subs[type]) {
// 判断在 subs是否有当前类型的 方法队列存在
this.subs[type] = []; // 没有就新增一个 默认为空数组
}
this.subs[type].push(fn); // 把方法加到该类型中
}
isFunction(fn) {
return fn && Object.prototype.toString.call(fn).includes('Function');
}
publish(type) {
// 发布
let fns = this.subs[type];
if (fns && Array.isArray(fns)) {
const args = Array.prototype.slice.call(arguments, 1); // 获取到参数
fns.forEach(fn=> fn(...args)); // 循环队列调用 fn
}
}
unsubscribe(type, fn) {
// 取消订阅
const currentEvents = this.subs[type];
if (currentEvents) {
const resObj = {
};
Object.keys(this.subs).forEach(eachSub=> {
if (eachSub !== type) {
resObj[eachSub] = this.subs[eachSub]
}
});
this.subs = resObj;
if (this.isFunction(fn)) {
fn();
}
}
}
}
export default PubSub;
2. Проверьте проект Vue
Например, родительский компонент shopList и два подкомпонента Book.vue/Pay.vue вводятся
во входной файл, например, и монтируют экземпляр main.js.main.js
pubSub
import PubSub from "../../../../Mark/prepare/概念实现/08.发布订阅";
Vue.prototype.$pubsub = new PubSub();
shopList.vue
<div class="fill-contain">
商家
<book/>
<pay/>
</div>
Pay.vue
<template>
<div>
<h1>我是收银台,您本次购买的图书价格是: {
{
cost}}</h1>
<h1>现在的时间是:{
{
nowTime}}</h1>
<el-button @click="initPubSub" type="primary">手动订阅</el-button>
</div>
</template>
<script>
export default {
name: "Pay",
data() {
return {
cost: 0,
nowTime: '',
}
},
mounted(){
this.initPubSub();
},
methods: {
initPubSub() {
this.$pubsub.subscribe('sendPay', (data, time)=> {
this.cost = data;
this.nowTime = time;
});
}
}
}
</script>
<style scoped>
</style>
Book.vue
<template>
<div>
<h1>买书</h1>
<el-button type="primary" @click="handleSendPay">发送价格</el-button>
<el-button type="primary" @click="handleCancelSub">取消订阅</el-button>
</div>
</template>
<script>
export default {
name: "Book",
methods: {
handleSendPay() {
this.$pubsub.publish('sendPay', 300, new Date().toLocaleString())
},
handleCancelSub() {
this.$pubsub.unsubscribe('sendPay', (d)=> {
console.log('取消订阅sendPay成功---', d);
})
},
}
}
</script>
В настоящее время существуют готовые реализации, основанные на концепции дизайна публикации-подписки в Vue 事件总线
. Обычно, когда я сталкиваюсь с динамическими компонентами, а именно с тегом <comComponent, я в первую очередь рассматриваю шину событий.