用jQuery和原生JavaScript实现发布订阅模式

通俗的说,发布订阅模式就是执行一个操作(如点击按钮,执行click事件)调用多个事件。
比如报社和订阅者。报社一更新报纸,订阅者就能接收到快递员传递过来的新报纸。

  • 一、jquery
    jquery.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button class="submit">submit</button>
<script src="dist/jquery.min.js"></script>
<script>

    // jQuery中的发布订阅思想 $.fire(),$.add(),$.remove()
    let f1 = function () {
        console.log("1")
    }
    let f2 = function () {
        console.log("2")
    }
    let f3 = function () {
        console.log("3")
    }
    // 1.非发布订阅的执行方法
    /*
        $('.submit').click(function () {
            f1();
            f2();
            f3();
        })
    */
    // 2. 发布订阅的执行方法
    // (1).创建一个事件池$.Callbacks()
    let $pond1 = $.Callbacks();
    $('.submit').click(function () {
        $pond1.fire(100,200);
    });
    let f4 = function (a,b) {
        console.log("4:",a+b)
    };
    // (2).需要做的事情添加到事件池中
    // 添加删除方法:$pond.add(fun) / $pond.remove(fun)
    $pond1.add(f1);
    $pond1.add(f2);
    $pond1.add(f3);
    $pond1.add(f4);
    // 移除方法
    $pond1.remove(f1)

</script>
</body>
</html>

  • 二、JavaScript
    1.封装方法subscribe.js
let _subscribe = (function() {
    // Sub:发布订阅类
    class Sub{
        constructor(){
            // 创建一个事件池,用来存储后期需要执行的方法
            this.$pond = [];
        }
        // 向事件池中添加方法(重复处理)
        add(func){
            let flag = this.$pond.some(item=>{
                return item === func
            });

            !flag? this.$pond.push(func) :null;
        }
        // 从事件池中移除方法
        remove(func){
            let $pond = this.$pond;
            for (let i=0;i<$pond.length;i++){
                let item = $pond[i];
                if(item === func){
                    // $pond.splice(i,1);移除,不能改变顺序splice,不能这样写,这样会
                    // 导致数组塌陷问题,我们移除不能真移除,只能把当前赋值为null
                    $pond[i] = null; // 1.设置为空,不改变索引
                    break;
                }
            }
        }

        //通知事件池中的方法,按照顺序依次执行
        fire(...args){
            let $pond = this.$pond;
            for (let i=0;i<$pond.length;i++){
                let item = $pond[i];
                if(typeof item !== 'function'){
                    // 删除
                    // 2.此时再删除
                    $pond.splice(i,1);// 删除后,索引需要变小
                    i--;
                    continue;
                }
                item.call(this,...args);
            }
        }
    }

    // 暴露给外面用
    return function subscribe() {
        return new Sub();
    }
})();

// let s1 = new Sub();
// 调用
// let s1 = _subscribe();

2.引用index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button class="submit">submit</button>
<script src="subscribe.js"></script>
<script>
    let pond = _subscribe();
    document.querySelector('.submit').onclick=function (ev) {
        pond.fire(ev);
    };
    let f1 = function () {
        console.log("1")
    };
    let f2 = function () {
        console.log("2");
        pond.remove(f1);// 这样会导致数组塌陷问题,结果:124;234;234 。.
        // 移除数组的某一项,索引向前移动,但是我们还在按照之前的顺序执行
    };
    let f3 = function () {
        console.log("3")
    };
    pond.add(f1);
    pond.add(f1); // 自己的方法有去重
    pond.add(f2);
    pond.add(f3);
    let f4 = function (ev) {
        console.log("4",ev)
    };
    pond.add(f4);
    // 移除
    // pond.remove(f2);
</script>
</body>
</html>

打印如图
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值