js设计模式——发布订阅模式和观察者模式

109 阅读1分钟

发布订阅模式和观察者模式有相同之处,都是一个对象发生变化另一个或多个对象会收到通知。

区别是观察者模式中观察者订阅目标对象后目标对象变化就会触发事件

发布订阅模式中存在一个中介者

一。观察者模式的两个应用

1.对windos全局对象的订阅观察

image.png 2.vue中的watch

image.png

二。发布订阅模式

实现vue2中的全局事件总线bus,用于兄弟组件通信,实现on,emit,off,once

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>

<body>
    <button class="on">on</button>
    <button class="emit">emit</button>
    <button class="off">off</button>
    <button class="on_once">注册一次性事件/button>
    <button class="emit_once">触发一次性事件</button>
</body>
<script>
    class myBus {
        handler = {};
        $on(event, callback) {
            if (this.handler[event] === undefined) {
                this.handler[event] = [];
            }
            this.handler[event].push(callback);
        }
        $emit(event, ...args) {
            const funcs = this.handler[event] || [];
            funcs.forEach((callback) => {
                callback(...args);
            });
        }
        $off(event) {
            this.handler[event] = undefined;
        }
        $once(event, callback) {
            this.$on(event, (...args) => {
                callback(...args);
                this.$off(event);
            })
        }
    }
    const bus = new myBus();

    document.querySelector(".on").addEventListener("click", function() {
        bus.$on("event1", (name) => {
            console.log(name);
        });
        bus.$on("event2", (name) => {
            console.log(name);
        });
    });
    document.querySelector(".emit").addEventListener("click", function() {
        bus.$emit("event1", "hello");
        bus.$emit("event2", "hello2");
    });
    document.querySelector(".off").addEventListener("click", function() {
        bus.$off("event1");
    });
    document
        .querySelector(".on_once")
        .addEventListener("click", function() {
            bus.$once("event3", (name) => {
                console.log(name);
            })
        });
    document
        .querySelector(".emit_once")
        .addEventListener("click", function() {
            bus.$emit("event3", "hello");
        });
</script>

</html>