EventEmitter 项目实战

作者: Kenny锅 | 来源:发表于2019-03-30 11:26 被阅读54次

    1.Background

    现有 APP 底部有 4 个 Tab 栏,Tabs 被一个类似 Frame 的页面包着,为了考虑性能与减少网络请求次数,只是首次进入会加载会 Tab 里的数据,所以QA与用户疯狂切 Tab,都是不请求数据,也不 rerender,真的如丝般顺滑。

    2.New feature

    好景不长,有一个带状态的列表要加入Tab 栏里来,列表有类似于「已购买」、「未购买」的状态,我们在详情页购买了,返回来要更新列表。

    3.Motivation

    第一时间想到的是 Redux ?很好,还有不同方案吗?对,就是 EventEmitter。

    Redux 已经在我们现有项目中大量使用,已经觉得很无趣了。我们试试EventEmitter 怎么样? Node.js 源码里有很多地方都会使用 EventEmitter,例如:net.Server 会在每次有新连接时触发事件,fs.ReadStream 会在打开文件时触发事件,stream 会在数据可读时触发事件等。

    我们为何不也学习一下呢? Come on, go ahead

    4.Code

    A、React Native 中的用法

    1、在项目入口文件处引用 import EventEmitter from 'EventEmitter'; ,React Native 已经内置了这个类,源码地址:node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js
    2、在项目入口文件(如:app.js 或 index.js)的 componentDidMount 里添加 global.CustomEventEmitter = new EventEmitter();
    3、在 Tab 页的 componentDidMount 里添加 Listener,global.CustomEventEmitter.addListener('tabListClick', this.getLatestData);
    4、在 Tab 页的 componentWillUnmount 里删除 Listener,global.CustomEventEmitter.removeListener('tabListClick', this.getLatestData);
    5、在 Detail 页面如果购买了,就调用global.CustomEventEmitter.emit('tabListClick');

    到这里用法已经就介绍完了,接下来简单介绍一下 EventEmitter 常用的 API:

    • addListener(eventType: string, listener: Function, context: ?Object)
      • eventType 为「事件名称」
      • listener 是一个回调的 function
      • context 表示 listener 调用时的上下文
    • removeListener(eventType: String, listener)
      • eventType 为「事件名称」
      • listener 是一个回调的 function
    • emit(eventType:string),传入一个「事件名称」

    注意:eventType 要保持一致,并且区别大小写

    其它 API 接口:
    • constructor(subscriber: ?EventSubscriptionVendor)
    • once(eventType: string, listener: Function, context: ?Object)
    • removeAllListeners(eventType: ?string)
    • removeCurrentListener()
    • removeSubscription(subscription: EmitterSubscription)
    • listeners(eventType: string)
    B、Node.js 中的用法
    • 在 Node.js 项目里的引用方式稍有不同 ,是const EventEmitter = require('events');
    • 在 Node.js 用了 on 做为 addListener 的别名,也就是说 on('eventName') == addListener('eventName')
    • 同理,用了 off 做为 removeListener 的别名,也就是说 off('eventName') == removeListener('eventName')
    • 调用时:emitter.emit('eventName');

    示例代码如下:

    const EventEmitter = require('events');
    class MyEmitter extends EventEmitter {}
    const myEmitter = new MyEmitter();
    myEmitter.on('eventName', (a, b) => {
      console.log(a, b, this);
      // 打印: a b {}
    });
    myEmitter.emit('eventName', 'a', 'b');
    

    这个例子的事件可以反复调用,只需调用:myEmitter.emit('eventName', 'a', 'b');

    如果你有一个场景是只需要执行一次事件(比如:记录项目首次启动),Node.js 也帮我们考虑进去了,如官方代码所示:

    const myEmitter = new MyEmitter();
    let m = 0;
    myEmitter.once('event', () => {
      console.log(++m);
    });
    myEmitter.emit('event');
    // 打印: 1
    myEmitter.emit('event');
    // 不触发
    
    Node.js 中 events 其它API:
    更多 Node.js 文章

    相关文章

      网友评论

        本文标题:EventEmitter 项目实战

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