《JS设计模式》读书笔记(三)

标签:JS 设计模式


读书笔记链接:


订阅发布模式

其实就是事件机制,可以实现异步。

通用的事件函数(自己写的)

   var event = (function(){
    var _nsList = {},
        _defaultNs = '__default__';

    function useNamespace(ns) {
        if(ns === undefined && _nsList[_defaultNs]) return _nsList[_defaultNs];
        if(_nsList[ns]) return _nsList[ns]

        var method = {
            sub: {},
            preEvent: {}, // key:[[args],[args],...]
            listen: function(key, fn) {
                if(!this.sub[key]) {
                    this.sub[key] = [];
                }
                this.sub[key].push(fn);
                // 如果有已经发生了的事件就立刻执行
                if(this.preEvent[key]) {
                    this.preEvent[key].forEach(function(args, index){
                        fn.apply(fn, args)
                    })
                    this.preEvent[key] = null;
                }
            },
            trigger: function() {
                var args = [];
                for(var i=0,l=arguments.length;i<l;i++){
                    args.push(arguments[i])
                }
                key = args.shift();
                if(!this.sub[key]) {
                    // 预发布事件
                    if(!this.preEvent[key]) this.preEvent[key] = [];
                    this.preEvent[key].push(args)
                } else if(this.sub[key].length > 0){
                    // 正常trigger
                    this.sub[key].forEach(function(fn, index){
                        fn.apply(fn, args);
                    });
                }
            },
            once: function(key, fn) {
                // 如果存在预发布的事件,那么就直接执行,并且不用监听了
                if(this.preEvent[key]) {
                    this.preEvent[key].forEach(function(args, index){
                        fn.apply(fn, args)
                    })
                    this.preEvent[key] = null;
                    return;
                }
                // 为了能够外部调用remove来手动删除
                if(!this.sub[key+'_once']) this.sub[key + '_once'] = [];
                this.sub[key + '_once'].push(fn);
                var that = this;
                var onceFn = function() {
                    that.remove(key, onceFn, that.sub)
                    fn.apply(that, arguments)
                }
                this.listen(key, onceFn, this.sub)
            },
            remove: function(key, fn) {
                if(!this.sub[key] || this.sub[key].length === 0) return;
                if(!fn) this.sub[key] = [];
                else {
                    for(var i=this.sub[key].length;i--;){
                        if(this.sub[key][i] === fn) {
                            this.sub[key].splice(i, 1);
                            return;
                        }
                    }
                    // 检查once的监听列表
                    if(!this.sub[key+'_once'] instanceof Array) return;
                    for(i=0,l=this.sub[key+'_once'].length;i<l;i++){
                        if(this.sub[key+'_once'][i] === fn) {
                            this.sub[key].splice(i, 1);
                            return;
                        }
                    }
                }
            },

        }
        if(ns === undefined) return _nsList[_defaultNs] = method;
        return _nsList[ns] = method;
    }
    return {
        defaultNs: useNamespace(),
        listen: function(key, fn) {
            this.defaultNs.listen(key, fn)
        },
        once: function(key, fn) {
            this.defaultNs.once(key, fn)
        },
        remove: function(key, fn) {
            this.defaultNs.remove(key, fn)
        },
        trigger: function(key, args) {
            this.defaultNs.trigger.apply(this.defaultNs, arguments)
        },
        useNamespace: useNamespace,
    }
}())
// 预发布
event.trigger('test', 10,213)
// 监听
var test;
event.listen('test', test = function(num,num2){
    console.log('testnum:',num,num2);
})
event.listen('test', function(msg){console.log(msg)})
event.once('test', function(msg){console.log('once', msg)})
// 触发三个事件
event.trigger('test', 11,0)
// 删除事件1
event.remove('test', test)
// 触发事件2
event.trigger('test', 222, 222)

但这个模式也有缺点,就是如果大量使用的话,会造成bug的跟踪困难


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,892评论 25 709
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 12,385评论 2 17
  • 1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined、Nul...
    极乐君阅读 10,989评论 0 106
  • 我的糖葫芦串,糖葫芦串……小小的女孩,扎着窜天辫,手里举着红红的糖葫芦串,却哭的稀里哗啦…… 在疲惫的梦境中醒来时...
    Jessy自由行走的猫阅读 3,297评论 0 4
  • 作者:海灵格我允许任何事情的发生。我允许,事情是如此的开始,如此的发展,如此的结局。因为我知道,所有的事情,都是因...
    十哥的九菇凉阅读 3,480评论 0 0