Implementation of the publish-subscribe principle in JS and Vue [a brief taste]

When I saw publish and subscribe in the past , I always thought it was a fixed code and some kind of algorithm. I recently learned about the responsiveness principle of Vue, and took a look at this by the way. Only to find out that it is just a design idea, record it in preparation for running.

1. Encapsulate the PubSub class

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. Verify in Vue project

For example, the parent component shopList and the two subcomponents Book.vue/Pay.vue are introduced
in the entry file such as and mount the instance main.jsmain.jspubSub

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>

Insert image description here
Currently, there are ready-made implementations based on publish-subscribe design ideas in Vue 事件总线. Generally, when I encounter dynamic components, namely the <component tag, I will first consider the event bus.

Guess you like

Origin blog.csdn.net/s18438610353/article/details/125524052