链式事件流轻量级迷你 JS 库 - hubJS

2,257 阅读2分钟
原文链接: zhuanlan.zhihu.com

使用情景

相信大家都听说过 RxJS,它无疑是优秀响应式编程库,让在很多事件驱动的 “流” 中随心所欲地为所欲为。

但实际到最近几次项目开发中,暴露了一些开发以外的问题。

首先想到就是对团队开发者的学习路线比较陡峭,特别是对一些前端新人,上手较为难,无法即拿即用。

另外就是功能真的太强大了,如果整个使用的话,带来冗余颇大,如果个别功能自行引入使用的话,也就意味着开发者需要熟悉其 API 封装。

而一些中小型项目,例如就像 Vue 非父子组件通讯,除了使用 “BUS” 概念之外,响应式编程的介入也是个不错的选择,但需要一个简单而轻便的库去支持。

于是封装了一个简单上手 事件流驱动的迷你 JS 库 - hubJS

开源 Github 地址是 github/yyued/hub.js

未进行 gzip 体积仅仅 6k,在实际几个项目上使用得到了不错的效果 :)

下载

可以通过 npm 进行安装

npm i hub-js --save

或者 直接 下载 min 版本,然后外链使用

<script src="./hub.min.js"></script>

使用

→ 简单用法

import $hub from 'hub-js';

// 注册监听 “test” 的监听器
$hub.listen('test', ( data ) => {
    console.log( 'test', data );
});

setInterval(( ) => {
    // 主动发送 “test” 事件
    $hub.emit('test', { code: 1 });
}, 1000);

→ 使用监听 DOM 原生事件

// 绑定 DOM 事件流 ( 可绑定多个 )
const dispatcher = $hub.DOM('button')
                       .from('click').emit('dom-click-event')
                       .from('mousedown').emit('dom-mousedown-event-1').emit('dom-mousedown-event-2');

// 监听 DOM 事件流
$hub.listen('dom-click-event', ( e ) => {
    console.log( 'button click', e );
})
$hub.listen('dom-mousedown-event-1', ( e ) => {
    console.log( 'button mousedown 1', e );
})
$hub.listen('dom-mousedown-event-2', ( e ) => {
    console.log( 'button mousedown 2', e );
})

setTimeout(function() {
    // 移除 DOM 监听事件,停止 发送事件流
    dispatcher.remove();
}, 10000);

→ 使用监听缓存值

// 设置 store 值
$hub.store.code = 1;

// 监听 store 里具体 某个数值
// 若 这个数值已存在 “当前值”,则监听成功后,立即返回 “当前值”,就像 Rx.BehaviorSubject
$hub.listen('@store/code', ( code ) => {
    console.log( 'store code', code );
})

setInterval(() => {
    // $hub.emit('@store/code', 1);
    ++$hub.store.code;
}, 1000);

→ 使用转换器 & 自由组合链式

// 注册转换器
$hub.converter.DOMEventFormat1 = function ( e ) {
    return [ e.type, e.target ];
}
$hub.converter.DOMEventFormat2 = function ( e ) {
    return [ e.target, e.type ];
}

// 可以通过自由组合 链式 衔接的顺序,进行对流的控制,从而达到你想要的效果
const dispatcher = $hub.DOM('button')
                      .from('click').convert('DOMEventFormat1').emit('dom-click-event')
                      .from('mousedown').convert('DOMEventFormat1').emit('dom-mousedown-event');

// 例如 还可以
// $hub.DOM('button').from('click').convert('DOMEventFormat1').emit('dom-click-event1').emit('dom-click-event2')
// $hub.DOM('button').from('click').convert('DOMEventFormat1').convert('DOMEventFormat2').emit('dom-click-event1')

// 监听 DOM 事件流
$hub.listen('dom-click-event', ( e ) => {
    console.log( 'button click', e );
})
$hub.listen('dom-mousedown-event', ( e ) => {
    console.log( 'button mousedown', e );
})

→ 使用链式通道

// 注册一个链式通道
$hub.chain('test').pipe(
   // 支持 Promise 阻塞
   ( d ) => new Promise( ( resolve ) => setTimeout( () => resolve( d + 1 ), 2000 ) ),
   ( d ) => d + 2,
   ( d ) => d + 3,
).pipe(
   ( d ) => d + 3,
);

// 监听链式通道回调
$hub.listen('@chain/test', ( d ) => {
    console.log( d );
})

// 触发
$hub.emit( '@chain/test', 1 ); // 10

更多

除了上述几种使用方式之外,hubJS 还支持 Fetch / WebSocket / socket.io 等多种事件源,欢迎大家使用并提出 issues。