zoukankan      html  css  js  c++  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>
  • 相关阅读:
    前言内容
    hibernate criteria中Restrictions的用法
    数据库默认端口
    MyEcplise2014集成SVN
    Java中的HashMap和HashTable到底哪不同?(原文参考来自码农网)
    MyEclipse控制台报错:java.lang.OutOfMemoryError: PermGen space
    版本管理软件Git 初感
    二分法,冒泡排序
    关于tail, head ,less ,more ,cat 之小介------Linux命令
    java:字符串反转
  • 原文地址:https://www.cnblogs.com/hutuzhu/p/4456034.html
Copyright © 2011-2022 走看看