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();

执行结果:

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

时间: 2024-08-28 21:56:21

JavaScript 事件管理的相关文章

JavaScript事件详解-zepto的事件实现

zepto的event 可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑源码暂且不表,github里还有中文网站都能下到最新版的zepto.整个event模块不长,274行,我们可以看到,整个event模块,事件绑定核心就是on和off,还有一个trigger用来触发,类观察者模式,可以先看看汤姆大叔的深入理解JavaScript系列(32):设计模式之观察者模式,其余皆为实现的处理函数.首先来个demo: $("#btn").on("click&quo

JavaScript 事件代理

转自:http://www.cnblogs.com/silence516/archive/2009/09/03/delegateEvent.html 如果你想给网页添加点JavaScript的交互性,也许你已经听过JavaScript的事件代理(event delegation),并且觉得这是那些发烧友级别的JavaScript程序员才会关心的什么费解的设计模式之一.事实上,如果你已经知道怎么添加JavaScript的事件处理器(event handler),实现事件代理也是件轻而易举的事情.

JavaScript事件代理和委托

在javasript中delegate这个词经常出现,看字面的意思,代理.委托.那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口.这些接口又有什么特殊的用法呢?这篇文章就主要介绍一下javascript delegate的用法和原理,以及Dojo,jQuery等框架中delegate的接口. JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的

Vue2-单一事件管理组件通信

对上篇文字[vue2.0 中#$emit,$on的使用详解]的实例运用: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Vue2-单一事件管理组件通信</title> 6 <script src="vue.js"></script> 7

javascript事件委托机制详解

以个人前端工作面试经历来看,javascript事件委托是问的最多的一类题目之一,熟悉事件委托能够了解你对于javascript的掌握程度. 面试官可能问一下问题,现在有5个li待办事件,需要实现当点击一个li时实现弹出该li的信息 <ul class="top"> <li>橘子</li> <li>香蕉</li> <li>苹果</li> <li>梨子</li> <li>

事件管理器

项目开发过程中经常会用到代理事件,为方便管理,避免代码混乱,需要一个总的事件管理器: using UnityEngine; using System.Collections; using System.Collections.Generic; using System; public class EventManager<T> { private static Dictionary<EventType,List<Action<T>>> eventDic =

JavaScript事件委托的技术原理

如今的JavaScript技术界里最火热的一项技术应该是‘事件委托(event delegation)’了.使用事件委托技术能让你避免对特定的每个节点添加事件监听器:相反,事件监听器是被添加到它们的父元素上.事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件.基本概念非常简单,但仍有很多人不理解事件委托的工作原理.这里我将要解释事件委托是如何工作的,并提供几个纯JavaScript的基本事件委托的例子. 假定我们有一个UL元素,它有几个子元素: <ul id="parent-l

JavaScript事件机制

<script type="text/javascript" src="http://runjs.cn/gist/2zmltkfa/all"></script> [前端培养-作业01]javascript事件机制 1.javascript事件模型 2.e.target与e.currentTarget是干什么的? 3.preventDefault与stopPropagation是干什么的 4.什么是dispatchEvent? 5.说一说事件代

javascript事件委托练习

JavaScript事件代理是一种简单的技巧,通过它你可以把事件处理器添加到一个父级元素上,这样就不需要为每一个元素添加或者删除事件处理器,从而避免了内存泄露或者是遍历节点造成的性能下降. 如果整个页面都采用同样事件流方式,当红色蓝色区域触发相同事件,冒泡法:先处理蓝色区域请求,捕获法:先处理红色区域请求 如果不同层的元素使用的useCapture不同,会先从最外层元素往目标元素寻找设定为capture(捕获)模式的事件,到达目标元素执行目标元素的事件后,再寻原路往外寻找设定为bubbling(