美文网首页ionic4 混合开发实战
ionic4-EventBus(事件总线)

ionic4-EventBus(事件总线)

作者: SandLZ | 来源:发表于2019-05-07 16:01 被阅读0次

    环境

    node 10.15.0
    ionic 4.12.0
    cordova 9.0
    # platforms
    cordova-android:8.0.0
    cordova-ios: 5.0.0
    

    前言:
    AngularJs 中,我们可以使用broadcast、on来发出、监听广播,实现全局的消息/事件通信;在Angular2+版本,取消了广播功能。
    下面我们将使用RxJS的特性来实现事件总线。
    注:代码源自ng-event-bus

    用法

    第一步

    导入

    # app.module.ts
    providers: [
      NgEventBus
    ]
    

    注入

    # some component
    constructor(private eventBus: NgEventBus){...}
    

    第二步

    发送事件

    this.eventBus.cast('test:start', {data: 'hahaha'});
    

    第三步

    接收事件

    # 接收单个
    this.eventBus.on('test:start').subscribe((message) => {
      console.log(message);
    });
    # 接收test下所有
    this.eventBus.on('test:**').subscribe((message) => {
      console.log(message);
    });
    

    源码分析

    事件定义

    interface EventBusMessage {
      key: string;
      data?: any;
    }
    

    this._eventBus 用于收发事件。
    此处为何使用Subject?

    什么是Subject(主题)?RxJS Subject是一种特殊类型的Observable,允许将值多播到多个观察者Observer。虽然普通的Observable是单播的(每个订阅的Observer都拥有Observable的独立执行),但Subject是多播的。

    每个Subject都是一个Observer。它是一个含有next(v),error(e)和complete()的对象。要向Subject提供新值,只需调用next(theValue),它将被多播到已注册接受该Subject的观察者。

    constructor() {
      this._eventBus = new Subject<EventBusMessage>();
    }
    

    发送事件

    如Subject的定义,只需调用next方法,就可已广播到所有订阅此Subject的观察者。

    public send(key: string, data?: any): void {
      if (typeof key !== 'string' || !key.length) {
        throw Error('key must be a string and mustn\'t be empty.');
      }
      this._eventBus.next({key, data});
    }
    

    接收事件

    参数:事件key
    filter:过滤key
    此处涉及到key匹配,下面单独说明

    public on<T>(key: string): Observable<T> {
      return this._eventBus.asObservable().pipe(
        filter((event: EventBusMessage): event is EventBusMessage => this.keyMatch(event.key, key)),
        map(event => <T>event.data)
      );
    }
    

    key匹配
    具体分析将以注释的形式展现

    public keyMatch(key: string, wildcard: string): boolean {
        const w = '*';
        const ww = '**';
        
        const partMatch = (wl, k) => {
          return (wl === w) || (wl === k);
        };
        const sep = this.separator;
        // 以*分割key etc: [app, start]
        const kArr = key.split(sep);
        // 监听key分割 etc: [app,**]
        const wArr = wildcard.split(sep);
        const kLen = kArr.length;
        const wLen = wArr.length;
        const max = Math.max(kLen, wLen);
        for (let i = 0; i < max; i++) {
          const cK = kArr[i];
          const cW = wArr[i];
          // 若:后匹配上** && :前不为undefined 则匹配上
          if (cW === ww && (typeof cK !== 'undefined')) {
            return true;
          }
          // :前后匹配, 2部分均不同 匹配失败
          if (!partMatch(cW, cK)) {
            return false;
          }
        }
        return true;
      }
    

    下一篇将介绍RxJS的订阅管理。

    相关文章

      网友评论

        本文标题:ionic4-EventBus(事件总线)

        本文链接:https://www.haomeiwen.com/subject/qloeoqtx.html