博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
据说每个大牛、小牛都应该有自己的库——Event处理
阅读量:7078 次
发布时间:2019-06-28

本文共 12226 字,大约阅读时间需要 40 分钟。

今天抽时间写了一部分Event处理方面的函数愈发的觉得jQuery的优秀,自己前期的想法太粗糙,造成后面这些函数参数很多,操作很很不直观,看样子是要重构的节奏,还好小伙儿伴们安慰,架构都是改出来的。继续探索吧

浏览器兼容性

写Event处理的库函数一个难点就在于浏览器兼容性问题,在IE低版本浏览器中事件对象始终在window.event属性中,而在其它浏览器中event会作为事件处理程序中作为第一个参数传入。而且其Event对象的属性和方法也有诸多差异,在中基本有所总结,不过还是抄一段关于事件处理程序绑定方面的差异

1. 参数个数不相同,这个最直观,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)

2. 第一个参数意义不同,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)

3. 事件处理程序的作用域不相同,addEventListener得作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window

4. 为一个事件添加多个事件处理程序时,执行顺序不同,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器

最简单的四个

先写四个最简单的

  • getEvent:获取事件对象
  • getTarget:获取事件源对象
  • preventDefault:阻止事件默认行为
  • stopPropagation:阻止事件冒泡

 

(function (window) {            var ssLib = {                getEvent: function (e) {                    return e ? e : window.event;                },                getTarget: function (e) {                    var e = this.getEvent(e);                    return e.target || e.srcElement;                },                preventDefault: function (e) {                    var e = this.getEvent(e);                    if (e.preventDefault) {                        e.preventDefault();                    } else {                        e.returnValue = false;                    }                },                stopPropagation: function (e) {                    var e = this.getEvent(e);                    if (e.stopPropagation) {                        e.stopPropagation();                    } else {                        e.cancelBubble = true;                    }                }            };            window.ssLib = window.ss = ssLib;        })(window);

代码很简单,相信聪明的小伙儿伴们一看就懂,就不多做解释了

addEvent/removeEvent

  • addEvent:为元素绑定事件处理程序
  • removeEvent:移除元素事件处理程序
addEvent: function (element, type, handler, key) {                    var key = key || handler;                    if (element[type + key])                        return false;                    if (typeof element.addEventListener != "undefined") {                        element[type + key] = handler;                        element.addEventListener(type, handler, false);                    }                    else {                        element['e' + type + key] = handler;                        element[type + key] = function () {                            element['e' + type + key](window.event);                        };                        element.attachEvent('on' + type, element[type + key]);                    }                    return true;                },                removeEvent: function (element, type, key) {                    if (!element[type + key])                        return false;                    if (typeof element.removeEventListener != "undefined") {                        element.removeEventListener(type, element[type + key], false);                    }                    else {                        element.detachEvent("on" + type, element[type + key]);                        element['e' + type + key] = null;                    }                    element[type + key] = null;                    return true;                },

这两个函数兼容性写法有很多,结合了很多大牛的写法后我用的上面版本,这么些看似很复杂,实际上主要解决了上面提到的、除了多个事件处理程序执行顺序问题的浏览器兼容性问题,比较难看懂的IE绑定部分就是为了处理this而写的。

在使用的时候,可以显示传入一个key用于内部识别绑定函数,如果不绑定则使用handler本身作为key,所以可以这么用

ssLib.addEvent(element,'click',function(){},'test');        ssLib.removeEvent(element,'click','test');                function handler(){}                ssLib.addEvent(element,'click',handler);        ssLib.removeEvent(element,'click',handler);

on/off

这个是看到jQuery的on/delegate和YUI 的delegate后萌发的想法,不过平时老用人家的没自己写过,仓促写了一个,感慨颇多,还是jQuery好使

on: function (parent, type, handler,validater,key) {                    var _key=key || handler;                    parent['on'+type+_key]=function (e) {                        var target = ssLib.getTarget(e);                        var isFire = validater(target);                        if (isFire) {                            target[type + _key] = handler;                            target[type + _key](e);                        }                    };                                        ssLib.addEvent(parent, type,parent['on'+type+_key] , key);                },                off: function (parent, type, key) {                    if(typeof key=='function'){                        ssLib.removeEvent(parent, type, parent['on'+type+key]);                    }else{                        ssLib.removeEvent(parent, type, key);                    }                    parent['on'+type+key]=null;                }

写法和刚才类似,不停的绕来绕去也是解决this问题,可以这么用

T1
T2

 

var parent = document.getElementById('test');                var handler=function () {            alert(this.id);        }                var validater=function (obj) {            if(obj.parentNode.id=='test'){                return true;            }else{                return false;            }        }                ss.on(parent, 'click', handler, validater);                ss.off(parent,'click',handler);                ss.on(parent, 'click', handler, validater,'delegate');                ss.off(parent,'click','delegate');

ready

用过jQuery的同学肯定知道这个函数,写自己库的时候是各种惊羡啊,于是乎加到了自己的库里

ready: function (fn) {                    if (document.addEventListener) {                        document.addEventListener("DOMContentLoaded", function () {                            document.removeEventListener("DOMContentLoaded", arguments.callee, false);// 防止多次调用                            fn();                        }, false);                    } else if (document.addEvent) {                        var doc = window.document, done = false;                        // only fire once                        var init = function () {                            if (!done) {                                done = true;                                fn();                            }                        };                        // polling for no errors                        (function () {                            try {                                // throws errors until after ondocumentready                                doc.documentElement.doScroll('left');// 文档加载完成后此方法可用                            } catch (e) {                                setTimeout(arguments.callee, 50);                                return;                            }                            // no errors, fire                            init();                        })();                        // trying to always fire before onload                        doc.onreadystatechange = function () {                            if (doc.readyState == 'complete') {                                doc.onreadystatechange = null;                                init();                            }                        };                    }                }

要想看懂上面代码最好看看

在现代浏览器中文档加载完后会触发“DOMContentLoaded”事件,而在底版本IE中文档加载完成后会doScroll方法会生效

Event部分源代码

(function (window) {            var ssLib = {                getEvent: function (e) {                    return e ? e : window.event;                },                getTarget: function (e) {                    var e = this.getEvent(e);                    return e.target || e.srcElement;                },                preventDefault: function (e) {                    var e = this.getEvent(e);                    if (e.preventDefault) {                        e.preventDefault();                    } else {                        e.returnValue = false;                    }                },                stopPropagation: function (e) {                    var e = this.getEvent(e);                    if (e.stopPropagation) {                        e.stopPropagation();                    } else {                        e.cancelBubble = true;                    }                },                addEvent: function (element, type, handler, key) {                    var key = key || handler;                    if (element[type + key])                        return false;                    if (typeof element.addEventListener != "undefined") {                        element[type + key] = handler;                        element.addEventListener(type, handler, false);                    }                    else {                        element['e' + type + key] = handler;                        element[type + key] = function () {                            element['e' + type + key](window.event);                        };                        element.attachEvent('on' + type, element[type + key]);                    }                    return true;                },                removeEvent: function (element, type, key) {                    if (!element[type + key])                        return false;                    if (typeof element.removeEventListener != "undefined") {                        element.removeEventListener(type, element[type + key], false);                    }                    else {                        element.detachEvent("on" + type, element[type + key]);                        element['e' + type + key] = null;                    }                    element[type + key] = null;                    return true;                },                ready: function (fn) {                    if (document.addEventListener) {                        document.addEventListener("DOMContentLoaded", function () {                            document.removeEventListener("DOMContentLoaded", arguments.callee, false);                            fn();                        }, false);                    } else if (document.attachEvent) {                        var doc = window.document, done = false;                        // only fire once                        var init = function () {                            if (!done) {                                done = true;                                fn();                            }                        };                        // polling for no errors                        (function () {                            try {                                // throws errors until after ondocumentready                                doc.documentElement.doScroll('left');                            } catch (e) {                                setTimeout(arguments.callee, 50);                                return;                            }                            // no errors, fire                            init();                        })();                        // trying to always fire before onload                        doc.onreadystatechange = function () {                            if (doc.readyState == 'complete') {                                doc.onreadystatechange = null;                                init();                            }                        };                    }                },                on: function (parent, type, handler, validater, key) {                    var _key = key || handler;                    parent['on' + type + _key] = function (e) {                        var target = ssLib.getTarget(e);                        var isFire = validater(target);                        if (isFire) {                            target[type + _key] = handler;                            target[type + _key](e);                        }                    };                    ssLib.addEvent(parent, type, parent['on' + type + _key], key);                },                off: function (parent, type, key) {                    if (typeof key == 'function') {                        ssLib.removeEvent(parent, type, parent['on' + type + key]);                    } else {                        ssLib.removeEvent(parent, type, key);                    }                    parent['on' + type + key] = null;                }            };            window.ssLib = window.ss = ssLib;        })(window);

转载于:https://www.cnblogs.com/dolphinX/p/3302360.html

你可能感兴趣的文章
HttpURLConnection和HttpClient的区别2(转)
查看>>
MYSQL-GroupCommit
查看>>
jboss CLI 命令行接口学习(适用JBOSS EAP 6.2+)
查看>>
lintcode:交错正负数
查看>>
前端学习-jQuery-2
查看>>
(轉載)教你怎样快速DIY自己的博客园SKIN
查看>>
SQL Server中关于基数估计如何计算预估行数的一些探讨
查看>>
第5条:避免创建不必要的对象
查看>>
使用UltraISO制作U盘启动盘
查看>>
过滤器第二篇【编码、敏感词、压缩、转义过滤器】
查看>>
半小时轻松玩转WebGL滤镜技术系列(一)
查看>>
实现一个可管理、增发、兑换、冻结等高级功能的代币
查看>>
【vue源码篇】filter源码详解
查看>>
React Native 报错
查看>>
【android精选】图片涂鸦下拉加载地图大集合五子棋游戏自定义上下文菜单源码...
查看>>
Git bug分支与多人协作
查看>>
反转单链表的方法
查看>>
python-14-描述符应用和类的装饰器
查看>>
帖子回复列表缓存优化日志
查看>>
单元测试利器Mockito框架
查看>>