js实现发布订阅

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>简单发布订阅</title>
</head>

<body>
  <!-- 
  在发布订阅模式中,有两个对象,一个是事件的发布者,一个是订阅者。
  简要思路:
    1.创建一个对象(缓存列表)
    2.on方法用来把回调函数fn都加到缓存列表中
    3.emit方法取到arguments里第一个当做key,根据key值去执行对应缓存列表中的函数
    4.remove方法可以根据key值取消订阅 
  -->
  <script>
    let event = {
      list: {},
      // 订阅事件
      on(key, fn) {
        // 如果对象中没有对应的key值
        // 也就是说明没有订阅过
        // 那就给key创建个缓存列表
        if (!this.list[key]) {
          this.list[key] = []
        }
        // 把函数添加到对应key的缓存列表里
        this.list[key].push(fn)
      },
      // 发布事件
      emit() {
        // 第一个参数是对应的key值,直接用数组的shift方法取出
        let key = [].shift.call(arguments),
          fns = this.list[key];
        // 如果缓存列表里没有函数就返回false
        if (!fns || fns.length === 0) {
          return false
        }
        // 遍历key值对应的缓存列表
        // 依次执行函数的方法
        fns.forEach(fn => {
          fn.apply(this, arguments)
        })
      },
      // 取消订阅事件
      remove(key, fn) {
        console.log('取消订阅事件');
        let fns = this.list[key];
        // 如果缓存列表中没有函数,返回false
        if (!fns) return false;
        // 如果没有传对应函数的话
        // 就会将key值对应缓存列表中的函数都清空掉
        if (!fn) {
          fns && (fns.length = 0);
        } else {
          // 遍历缓存列表,看看传入的fn与哪个函数相同
          // 如果相同就直接从缓存列表中删掉即可
          fns.forEach((cb, i) => {
            if (cb == fn) {
              fns.splice(i, 1)
            }
          })
        }
      }
    }

    function cat() {
      console.log('我是一只猫');
    }

    function dog() {
      console.log('我是旺财');
    }

    event.on('pet', data => {
      console.log(data);
    });
    event.on('pet', cat);
    event.on('pet', dog);
    // 取消dog方法的订阅
    event.remove('pet', dog);
    // 发布
    event.emit('pet', ['波斯猫1', '琵琶狗1'])
  </script>
</body>

</html>
// 触发事件两个参数(事件名,参数)
  emit (type, ...params) {
    // 若没有注册该事件则抛出错误
    if (!(type in this.handlers)) {
      return new Error('未注册该事件')
    }
    // 便利触发
    this.handlers[type].forEach(handler => {
      handler(...params)
    })
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值