Harley Wang

为了心中的美好,不妥协直到变老

Technical discuss & life Note-taking.


PigeonJs

PigeonJs 是一个轻量级自定义事件或观察者模式的实现。

特点:

  • 小巧,不依赖任何lib
  • 单例模式实现,任意地方可添加订阅,移除订阅,清除事件类型;
  • 支持单事件触发和群组触发,单事件移除和群组移除;
  • 移除订阅只需通过namespace命令空间,因为有时添加订阅和移除阅订不在一个作用域下, 这样会带来极大的方便;
  • 安全的handlers事件存储,不会被无意中覆盖;

NameSpace格式:

type.key : type 为事件的类型,表示群组;key 为订阅的唯一标识符

注意:不支持多层命名空间(例如:uxdc.haleywang.age),第二层后面的部分会被忽略掉

源码:

/**
 * pigeon.js
 *
 * Release 1.2.0
 * @author <a href="mailto:harley.wang.vip@gmail.com">Harley Wang</a>
 * @describe  一个轻量级自定义事件或观察者模式的实现。
 */

(function(global, factory) {
    'use strict';
    if (typeof exports === "object" && exports) {
        factory(exports); // CommonJS
    } else if (typeof define === "function" && define.amd) {
        define(['exports'], factory); // AMD
    } else {
        factory(global.PigeonJs = {}); // <script>
    }
}(window, function(PigeonJs) {
    'use strict';

    var handlers = {};
    var splitStr = function(ns){
        var values = ns.split('.', 2);
        return {'type':values[0], 'key':values[1]};
    },
    clearHandlers = function(type){
        delete handlers[type];
    };
    /**
     * 添加事件
     * @param  {String} namespace   命名空间,格式必须为:type.key
     * @param  {Function} handler   触发函数
     */
    PigeonJs.addHandler = function(namespace, handler){
        var ns = splitStr(namespace);
        if(typeof handlers[ns.type] == 'undefined'){
            handlers[ns.type] = [];
        }else{
            this.removeHandler(namespace);
        }
        handlers[ns.type].push( {'unique':ns.key, 'handler':handler} );
    };
    /**
     * 移除事件
     * @param  {string} namespace    命名空间,为:type.key 或 type
     */
    PigeonJs.removeHandler = function(namespace){
        var ns = splitStr(namespace);
        if(ns.type && !ns.key){
            clearHandlers(ns.type);
        }
        else if(handlers[ns.type] instanceof Array){
            var events = handlers[ns.type];
            for(var i=0,len=events.length; i<len; i++){
                if(events[i]['unique'] == ns.key){
                    events.splice(i, 1);
                    break;
                }
            }

            if(events.length == 0){
                clearHandlers(ns.type);
            }
        }
    };
    /**
     * 触发器
     * @param  {string} namespace                                   命名空间,格式为:type.key 或 type
     * @param  {Object|Array|String|Boolean|Number|Function} data   要传递的数据,可选
     */
    PigeonJs.trigger = function(namespace, data){
        var ns = splitStr(namespace);

        if(handlers[ ns.type ] instanceof Array){
            var events = handlers[ns.type];
            for(var i=0,len=events.length; i<len; i++){
                if(ns.key){
                    if(events[i]['unique'] == ns.key){
                        events[i]['handler'](ns, data);
                        break;
                    }
                }else{
                    events[i]['handler'](ns, data);
                }
            }
        }
    };

}));

Example:


// 添加订阅
PigeonJs.addHandler('uxdc.haleywang', function(ns, event){
    console.log(ns, event.message, '我是haleywang,收到!');
});

// 添加订阅
PigeonJs.addHandler('uxdc.ice', function(ns, event){
    console.log(ns, event.message, '我是ice,收到!');
});

// 添加订阅
PigeonJs.addHandler('uxdc.ouyi', function(ns, event){
    console.log(ns, event.message, '我是ouyi,收到!');
});


// 触发
PigeonJs.trigger('uxdc.ouyi', {message:"2:00 来duang2会议室开会!"});
PigeonJs.trigger('uxdc.haleywang', {message:"4:00 上线!"});
PigeonJs.trigger('uxdc.ice', {message:"带个早点上楼!"});

// 触发群组
PigeonJs.trigger('uxdc', {message:"@all:明天放假一天!"});

// 移除订阅
PigeonJs.removeHandler('uxdc.haleywang');
// 触发群组
PigeonJs.trigger('uxdc', {message:"@all:写周报!"});

// 移除群组
PigeonJs.removeHandler('uxdc');

在React中使用:

使用 PigeonJs 在组件之间进行通讯或数据共享:

// 快捷菜单
var ShortcutMenu = React.createClass({
    getInitialState: function() {
        return {selected: this.props.selected};
    },
    show: function(){
        this.refs.shortcut_menu.style.display = 'block';
    },
    hide: function(){
        this.refs.shortcut_menu.style.display = 'none';
    },
    componentDidMount: function(){
        var that = this;
        PigeonJs.addHandler('ShortcutMenu.onShow', function(ns, event){
            that.show();
        });
    },
    componentWillUnmount: function(){
        PigeonJs.removeHandler('ShortcutMenu.onShow');
    },
    render: function() {
        return (
            <div ref="shortcut_menu" className="shortcut_menu"></div>
        );
    }
});
ReactDOM.render(<ShortcutMenu />, document.getElementById('shortcut_menu'));

在其它组件中触发:

// 更多快捷菜单
onMore: function(e){
    PigeonJs.trigger('ShortcutMenu.onShow');
}

GitHub地址:https://github.com/harleywang/PigeonJs

最近的文章

使用gin踩过的坑

永久(301)和临时(301)跳转问题目前很多浏览器(例如: Chrome)开始缓存301请求,缓存后访问A Url会被直接在浏览器端跳转到B Url;在gin中可能会导致router B Url不会收到请求;在SEO方面还会将关键词排名和PR级别传给B Url,当然还会影响Squid的缓存结果;gin 的301跳转方法如下:c.Redirect(http.StatusMovedPermanently, "/login")gin 的302跳转方法如下:c.Redirect(http.Sta...…

golang,gin继续阅读
更早的文章

我的逗比小伙伴

还在得实大厦办公的时候,很多次加班到凌晨都要去海底捞填饱肚子(因为其他店都打烊了);当然这一天也不例外,吃过饭回来的路上应小伙伴要求,来到了我们即将要搬的新家——安宁庄办公区,过来转转,看看。于是,留下了几张逗比的合影。当时现场只有我们四个人,有人问那你们是怎么拍的,哈哈,你猜吧!…

继续阅读