zoukankan      html  css  js  c++  java
  • JavaScript 事件管理

     在设计JavaScript xxsdk的时候考虑到能让调用者参与到工作流程中来,开始用了回调函数。如下:

    this.foo = function(args,callbackFn) {
          //do something
            //then  if callbackFn is a function
           callbackFn();
     };

    或者在初始化的传入config。

     function SDK(config) {
                var configs = {
                    onInit: function() {
                    },
                    onFoo: function () {
                    },
                    // on....
                };
                //合并参数
                configs = $.extend(configs, config);
                this.foo = function (args) {
                    //do something
                    configs.onFoo();
                };
    }

    但问题来了,随着函数越多,第一种方式就显得很烦,每个方法的参数后面要跟一个或者多个回调函数,代码显得不干净,而且只有用户调用的时候才会执行回调,对于没有暴露给用户的方法就用不上。第二种方式,函数越多,config就越长,构造代码显得难看,另一方面就是一个方法只会触发一个回调。最后使用了下面的方式

    事件管理

    先定义一个事件管理器,主要思路是让每一个事件类型对应一个回调列表,这样可以让外部对同一个事件关联多次。取消某个关联就是在该事件类型的函数列表中移除某个回调函数。触发就是把列表中函数全部执行一遍。当然还带上了参数。

     var eventManger = {                
                    handlers: {},
                    //类型,绑定事件 
                    addHandler:function(type,handler) {
                        if (typeof this.handlers[type] == "undefined") {
                            this.handlers[type] = [];//每个事件都可以绑定多次
                        }
                        this.handlers[type].push(handler);
                    },
                    removeHandler:function(type, handler) {
                        var events = this.handlers[type];
                        for (var i = 0, len = events.length; i < len; i++) {
                            if (events[i] == handler) {
                                events.splice(i, 1);
                                break;
                            }
                        }
                    },
                    trigger: function (type) {
                        if (this.handlers[type] instanceof Array) {
                            var handlers = this.handlers[type];
                            var args = Array.prototype.slice.call(arguments, 1);
                            for (var i = 0, len = handlers.length; i < len; i++) {
                                handlers[i].apply(null, args);
                            }
                        }
                    }
                };

    然后在sdk中公布关联和移除的方法:

     //给外部绑定事件
                this.on = function(type, event) {
                    eventManger.addHandler(type,event);
                };
                //移除事件
                this.off = function(type, event) {
                    eventManger.removeHandler(type, event);
                };

    在执行的过程中分别触发事件:

               this.init = function() {
                    //do init
                    eventManger.trigger('init');
                };
                this.start = function() {
                    //do start
                    eventManger.trigger('start');
                };
                this.connect = function() {
                    eventManger.trigger('connect');
                };
                this.messages = function() {
                    var msgs = [];
                    msgs.push("你好吗");
                    msgs.push("我很好");
                    eventManger.trigger('messages',msgs);
                };
                this.disconnect = function() {
                    eventManger.trigger('disconnect');
                };

    那用户在使用的时候就比较方便了。

    //绑定connect
     sdk.on('connect', function () {
                console.log('connect');
            });
    //绑定messages
            sdk.on('messages', function (data) {
                if (!data) return;
    
                if (data instanceof Array) {
                    for (var i = 0; i < data.length; i++) {
                        console.log(data[i]);
                    }
                } else {
                    console.log(data);
                }
           });

    还可以先绑定,移除再绑定。

    var oninit = function() {
                console.log('init...');
            };
     sdk.on('init', oninit);
     sdk.on('init', function () {
                console.log('other init');
            });
     sdk.off('init', oninit);
            sdk.init();

    全部代码:

        function SDK() {
    
                var eventManger = {                
                    handlers: {},
                    //类型,绑定事件 
                    addHandler:function(type,handler) {
                        if (typeof this.handlers[type] == "undefined") {
                            this.handlers[type] = [];//每个事件都可以绑定多次
                        }
                        this.handlers[type].push(handler);
                    },
                    removeHandler:function(type, handler) {
                        var events = this.handlers[type];
                        for (var i = 0, len = events.length; i < len; i++) {
                            if (events[i] == handler) {
                                events.splice(i, 1);
                                break;
                            }
                        }
                    },
                    trigger: function (type) {
                        if (this.handlers[type] instanceof Array) {
                            var handlers = this.handlers[type];
                            var args = Array.prototype.slice.call(arguments, 1);
                            for (var i = 0, len = handlers.length; i < len; i++) {
                                handlers[i].apply(null, args);
                            }
                        }
                    }
                };
                //给外部绑定事件
                this.on = function(type, event) {
                    eventManger.addHandler(type,event);
                };
                //移除事件
                this.off = function(type, event) {
                    eventManger.removeHandler(type, event);
                };
    
                this.init = function() {
                    //do init
                    eventManger.trigger('init');
                };
                this.start = function() {
                    //do start
                    eventManger.trigger('start');
                };
                this.connect = function() {
                    eventManger.trigger('connect');
                };
                this.messages = function() {
                    var msgs = [];
                    msgs.push("你好吗");
                    msgs.push("我很好");
                    eventManger.trigger('messages',msgs);
                };
                this.disconnect = function() {
                    eventManger.trigger('disconnect');
                };
    
                this.autoRun = function() {
                    this.init();
                    this.start();
                    this.connect();
                    this.messages();
                    this.disconnect();
                };
    
                
    
            }
    
            var sdk = new SDK();
            var oninit = function() {
                console.log('init...');
            };
            sdk.on('init', oninit);
            sdk.on('start', function () {
                console.log('start');
            });
            sdk.on('connect', function () {
                console.log('connect');
            });
            sdk.on('messages', function (data) {
                if (!data) return;
                
                if (data instanceof Array) {
                    for (var i = 0; i < data.length; i++) {
                        console.log(data[i]);
                    }
                } else {
                    console.log(data);
                }
            });
            sdk.on('disconnect', function () {
                console.log('disconnect');
            });
    
            sdk.autoRun();
            sdk.on('init', function () {
                console.log('other init');
            });
            sdk.off('init', oninit);
            sdk.init();
    View Code

    执行结果:

    还可以扩展一些方法once() 、removeListener() 、removeAllListeners()֖等

    小结:事件的处理方式更加简洁且更有扩展性。jquery的事件机制没有将事件监听函数绑定到DOM元素上,而是基于数据缓存模块来管理的。这里借鉴了下,对同一事件类型type的所有监听对象handleObj构成监听对象数组handles。因为没有涉及到dom操作,所以相对也简单些。

  • 相关阅读:
    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
    便携版WinSCP在命令行下同步文件夹
    ffmpeg (ffprobe)分析文件关键帧时间点
    sqlite删除数据或者表后,回收数据库文件大小
    ubuntu 20.04下 freeswitch 配合 fail2ban 防恶意访问
    ffmpeg使用nvenc编码的结论记录
    PC版跑跑卡丁车 故事模式 亚瑟传说章节 卡美洛庆典 2阶段 心灵之眼 攻略
    There was an error loading or playing the video
    Nvidia RTX Voice 启动报错修复方法
    火狐浏览器 关闭跨域限制
  • 原文地址:https://www.cnblogs.com/stoneniqiu/p/5479246.html
Copyright © 2011-2022 走看看