目录
归档
123
2017 年 04 月 04 日
mitt — 只有200b的事件监听/触发函数

github地址:https://github.com/developit/mitt

这个函数实在精简,拿来分析一下怎么写的。


// @flow
// 定义三个flow静态检查的类型,分别是事件处理器,事件处理器列表,事件处理列表组成的对象
type EventHandler = (event?: any) => void;
type EventHandlerList = Array<EventHandler>;
type EventHandlerMap = {
  [type: string]: EventHandlerList
};

//导出一个函数,参数为一个上面定义的对象类型
export default function mitt(all: EventHandlerMap) {

  //一个典型的闭包结构

  //判断是否是否传入对象,假如没有则新建一个无原型继承的空对象all
  //且每次运行return里的函数时all都不会被销毁
  all = all || Object.create(null);

  return {
    //事件监听,接受两个参数,分别是所监听的字符串名字type,和处理事件器handler
    //先检查all对象是否已经含有type属性,没有则z在all中为type新建一个空数组
    //最后把handler添加到数组
    on(type: string, handler: EventHandler) {
      (all[type] || (all[type] = [])).push(handler);
    },

    //事件移除,接受两个参数,分别是所监听的字符串名字type,和处理事件器handler
    //根据type查找到all中要被删除事件列表,假如没有则使用一个空数组
    //根据handler名字找到对应index,最后移除事件列表上的该handler
    off(type: string, handler: EventHandler) {
      let e = all[type] || (all[type] = []);
      e.splice(e.indexOf(handler) >>> 0, 1);
    },

    //事件触发,接受两个参数,分别是需触发的字符串名字type,和传入的参数evt
    //首先根据type查找到对应的事件列表,没有对应则使用空数组,接着以evt参数触发数组上每个函数
    //all有一个特殊属性就是 * ,上面的事件列表只要每次emit,都会以type和evt作为参数触发每个函数
    emit(type: string, evt: any) {
      (all[type] || []).map(handler => {
        handler(evt);
      });
      (all["*"] || []).map(handler => {
        handler(type, evt);
      });
    }
  };
}


分析一下使用时的数据结构


//引入mitt,mitt为导出的函数
import mitt from 'mitt'

//mitt函数返回值为一个对象,这里也可以传入初始对象作为参数
//此时all = {}
let emitter = mitt();

//监听一个名为"foo"的监听器
//此时 all = { 'foo': [ e => console.log('foo', e) ] }
emitter.on('foo', e => console.log('foo', e) )

//监听所有事件
//此时 all = { foo: [ e => console.log('foo', e), '*' : [(type, e) => console.log(type, e)] }
emitter.on('*', (type, e) => console.log(type, e) )

//触发"foo"监听器
emitter.emit('foo', { a: 'b' })


转载原创文章请注明,转载自: 老赵茶馆 » mitt — 只有200b的事件监听/触发函数
留言
Loading...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

  1. 喜帖街 谢安琪
  2. 猫の恩返 室内管弦楽団