js实现对主题的订阅(topic订阅),内附源码

有不合理和错误的地方欢迎小伙伴雅正,与大家共勉

理解对主题订阅

angular中的订阅的实现是用的RX.js库,我们可以用Subject来实现事件的订阅和发布

// 声明一个可观察对象
const obervable = new Subject();
// 订阅
observable.subscript( data => {
    handler...
})
// 发布
observable.next(data)

项目中离不了对同一个可观察对象的不同主题的订阅,比如单页面应用中某个负责权限的可观察对象,进行登录和登出这两个主题进行订阅,这个可观察会根据用户的登录和登出去订阅者发布登录和登出的事件,让订阅者去执行异形系列的操作(大型项目中这有利于降低功能间的耦合)

// 声明一个可观察对象,也是一个事件发布对象
const obervable = new Events();
// 对某个话题订阅
obervable.subscript("login",handler)
obervable.subscript("logout",handler)
// 对某个主题发布实践
observable.publish("login",data)
observable.publish("logout",data)

给大家看个熟悉的,jQuery的on方法,方便小伙伴理解

// 选取一个dom元素
const dom = $("#obervableDom")
// 对这个dom元素的主题进行订阅(事件监听)
dom.on("click",handler)
// dom元素发布主题(触发事件)
dom.click()

熟悉ionic的小伙伴可能有话说了,这不就是ionic的Events吗。这就是ionic的Events,不过想不明白RX.js这么优秀的一个库怎么会没有实现对主题的订阅这个功能呢,是不是RX.js中有替代方法,有小伙伴知道的话欢迎给我说一下,不胜感激。

下面是我根据ionic Events类的思路和代码重写的一个新的Events,用了一些ES6的语法。用法文档没有变化(?????我也感觉我是在抄袭了,就当给小伙伴推广Ionic 的Events了)

实例方法文档

publish(topic, eventData)

对某个主题发布数据,触发对某个主题订阅的回调函数
| 参数 |类型|备注|
topicstring要发布的主题名称
eventDataany发送给订阅此主题的事件(函数)的数据

subscribe(topic, handler)

对某个主题进行订阅,发布该主题的事件时,会出发handler回调函数,handler的形参就是发布主题给的数据
| 参数 |类型|备注|
topicstring要订阅的主题名称
handlerfunction处理发布事件数据的回调函数

unsubscribe(topic, handler)

对某个主题取消订阅,将不再处理该主题的发布事件, 释放内存
| 参数 |类型|备注|
topicstring要取消订阅的主题名称
handlerfunction要取消订阅的处理函数

实例

// 声明一个可观察对象,也是一个事件发布对象
const obervable = new Events();
// 对某个话题订阅
obervable.subscript("topic1",handler)
obervable.subscript("topic2",handler)
// 对某个主题发布实践
observable.publish("topic1",data)
observable.publish("topic2",data)

源码


export class NgEventsService {
  // 用来存储订阅主题和该主题的回调的函数 {topicName:[handlerfun]}
  private static channel;

  // 对某个主题进行订阅,发布该主题的事件时,会出发handler回调函数,handler的形参就是发布主题给的数据
  subscribe(topic: string, ...handlers) {
    if (handlers.length === 0) {
      return;
    }
    if (!NgEventsService.channel[topic]) {
      NgEventsService.channel[topic] = [];
    }
    NgEventsService.channel[topic].push(...handlers);
  }
  // 对某个主题发布数据,触发对某个主题订阅的回调函数
  publish(topic, ...handlers) {
    const channelTopic = NgEventsService.channel[topic];
    if (!channelTopic) {
      return null;
    }
    const responses = [];
    channelTopic.forEach(handler => {
      responses.push(handler.apply(0[0], handlers));
    });
    return responses;
  }
  // 对某个主题取消订阅,将不再处理该主题的发布事件
  unsubscribe(topic, handler) {
    const channelTopic = NgEventsService.channel[topic];
    if (!channelTopic) {
      return false;
    }
    if (!handler) {
      delete NgEventsService.channel[topic];
      return true;
    }
    const indexflag = channelTopic.indexOf(handler);
    if (indexflag < 0) {
      return false;
    }
    channelTopic.slice(indexflag, 1);
    if (channelTopic.length = 0) {
      delete NgEventsService.channel[topic];
    }
    return true;
  }
}

?????如果能帮助到小伙伴的话欢迎点个赞?????
?????如果能帮助到小伙伴的话欢迎点个赞?????

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值