你的位置:首页 > Java教程

[Java教程]高级功能:很有用的javascript自定义事件


之前写了篇文章《原生javascript实现类似jquery on方法的行为监听》比较浅显,能够简单的使用场景。

这里的自定义事件指的是区别javascript默认的与DOM交互的事件,比如click,mouseover,change等,有时候我们需要监听某一行为是否发生,很显然默认的行为不够用,比如一个场景。我们写好了tab切换,点击后请求加载隐藏标签的内容。

tab切换是非常常用的一个功能,通常会写成组件,如果每次把请求写在组件里肯定对组件拓展和耦合性有影响。这时候我们可以在组件里自定义一个事件广播,在其他地方监听这个广播再执行请求就可以避免了。

以上只是使用场景,下面是具体实现:

1、简易代码,基础功能:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>自定义事件</title></head><body>  <button id="demo">点我吧</button>  <script type="text/javascript">    function Observer(){      this._events={};    }    Observer.prototype={      on:function(eName,fn,scope){        eName=eName.toLowerCase();        this._events[eName]=[];        this._events[eName].push({fn:fn||null,scope:scope||null});      },      fireEvent:function(){        var args=Array.prototype.slice.call(arguments);//将参数转为数组        var eName=args.shift().toLowerCase();        var list=this._events[eName];        for(var i=0;i<list.length;i++){          var dict=list[i];          var fn=dict.fn;          var scope=dict.scope;          fn.apply(scope||null,args);//注册事件执行        }      }    }    var listener=new Observer();    listener.on("alert",function(name ,age){      console.log(name+":"+age);    });    listener.on("aha",function(name ,age){      console.log("这是另外一个事件"+name+":"+age);    });    var $btn=document.getElementById("demo")    $btn.onclick=function(){      listener.fireEvent('aha', '彼岸花再开', 28);    }  </script></body></html>

有点类似jquery里面的on方法,$(ele).on(type,fn)。上面的on是注册一个事件,这个事件是一个对象,存储当前的事件名称和函数。fireEvent可以理解为释放,发射,监听事件。

完整的实现:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>自定义事件</title></head><body>  <button id="demo">点我吧</button>  <script type="text/javascript">    function Observer() {      this._events = {};    }    Observer.prototype = {      constructor: this,      addEvent: function(eName, fn) {        if (typeof(eName) === "string" && typeof(fn) === "function") {          eName = eName.toLowerCase();          if (typeof(this._events[eName]) === "undefined") {            this._events[eName] = [fn];          } else {            this._events[eName].push(fn);          }        }        return this;      },      addEvents: function(obj) { //绑定多事件        obj = typeof(obj) === "object" ? obj : {};        for (var eName in obj) {          if (eName && typeof(obj[eName] === "function")) {            this.addEvent(eName, obj[eName]);          }        }        return this;      },      fireEvent: function(eName) { //触发事件        if (eName && this._events[eName]) {          var events = {            eName: eName,            target: this          };          for (var length = this._events[eName].length, start = 0; start < length; start++) {            this._events[eName][start].call(this, events);          }        }        return this;      },      fireEvents: function(array) {        if (array instanceof Array) {          for (var i = 0, len = array.length; i < len; i++) {            this.fireEvent(array[i]);          }        }        return this;      },      removeEvent: function(eName, key) { //删除绑定的事件        var eventsList = this._events[eName];        if (eventsList instanceof Array) {          if (typeof(key) === "function") {            for (var i = 0, len = eventsList.length; i < len; i++) {              if (eventsList[i] === key) {//移除其中某个事件                eventsList.splice(i, 1);                break;              }            }          } else if (key instanceof Array) {//移除某个事件下面多个函数            for (var lis = 0, lenkey = key.length; lis < lenkey; lis += 1) {              this.removeEvent(type, key[lenkey]);            }          } else {//直接移除事件下所有函数            delete this._events[eName];          }        }        return this;      },      removeEvents: function(params) {        if (params instanceof Array) {          for (var i = 0, length = params.length; i < length; i += 1) {            this.removeEvent(params[i]);          }        } else if (typeof params === "object") {          for (var type in params) {            this.removeEvent(type, params[type]);          }        }        return this;      }    }    var listeners = new Observer();    listeners.addEvents({      "once": function() {        alert("该事件只会出现一次!");        this.removeEvent("once");      },      "infinity": function() {        alert("每次点击页面,该事件都会!");      }    });    document.onclick = function(e) {      e = e || window.event;      var target = e.target || e.srcElement;      if (!target || !/button/i.test(target.tagName)) {        listeners.fireEvents(["once", "infinity"]);      }    };  </script></body></html>

 换apply实现,细心的你是否发现其中的差别呢:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>自定义事件</title></head><body>  <button id="demo">点我吧</button>  <script type="text/javascript">    function Observer() {      this._events = {};//存储事件对象    }    Observer.prototype = {      constructor: this,      addEvent: function(eName, fn) {//绑定事件        if (typeof(eName) === "string" && typeof(fn) === "function") {          eName = eName.toLowerCase();          if (typeof(this._events[eName]) === "undefined") {            this._events[eName] = [{//将事件函数绑定到事件名称              fn: fn            }];          } else {            this._events[eName].push({              fn: fn            });          }        }        return this;      },      addEvents: function(obj) { //绑定多事件        obj = typeof(obj) === "object" ? obj : {};        for (var eName in obj) {          if (eName && typeof(obj[eName] === "function")) {            this.addEvent(eName, obj[eName]);          }        }        return this;      },      fireEvent: function(eName) {//广播事件,射吧!        var args = Array.prototype.slice.call(arguments);//将参数转为数组        var eName = args.shift().toLowerCase();//第一个参数是事件名,这里需要除时间名之外的参数        var list = this._events[eName];        if(list instanceof Array){          for (var i = 0; i < list.length; i++) {          var dict = list[i];          var fn = dict.fn;          fn.apply(null, args);          }        }        return this;      },      fireEvents: function(array) {        if (array instanceof Array) {          for (var i = 0, len = array.length; i < len; i++) {            this.fireEvent(array[i]);          }        }        return this;      },      removeEvent: function(eName, key) {        var eventsList = this._events[eName];        if (eventsList instanceof Array) {          if (typeof(key) === "function") {            for (var i = 0, len = eventsList.length; i < len; i++) {              if (eventsList[i] === key) {                eventsList.splice(i, 1);                break;              }            }          } else if (key instanceof Array) {            for (var lis = 0, lenkey = key.length; lis < lenkey; lis += 1) {              this.removeEvent(type, key[lenkey]);            }          }else{             delete this._events[eName];          }        }      }    }    var listeners = new Observer();    listeners.addEvents({      "once": function() {        alert("该事件只会出现一次!");        listeners.removeEvent("once");      },      "infinity": function() {        alert("每次点击页面,该事件都会出现!");      }    });    document.onclick = function(e) {      e = e || window.event;      var target = e.target || e.srcElement;      if (!target || !/input|pre/i.test(target.tagName)) {        listeners.fireEvents(["once", "infinity"]);      }    };  </script></body></html>