事件模块
1、提供其他DOM方法
- 包括:
next
和nextAll
方法
1.1 next方法实现
- 目标:扩展框架方法,获取当前元素的下一个元素
- 问题:如何获取下一个元素?
1.1.1 提供 nextSibling 工具方法
- 说明:这是一个工具型方法,用来获取指定元素的下一个元素
itcast.extend({ nextSibling: function(dom) { var nextNode = dom; while(nextNode = nextNode.nextSibling) { if(nextNode.nodeType === 1) { return nextNode; } } } });
1.1.2 next方法
itcast.fn.extend({ next: function() { var arr = []; itcast.each(this, function() { arr.push( itcast.nextSibling(this) ); }); return itcast(arr); } });
1.2 nextAll方法实现
- 目标:扩展框架方法,获取当前元素后面所有元素
1.2.1 提供 nextAll 工具方法
- 工具方法:获取后面所有元素 - nextAll
itcast.extend({ nextAll: function(dom) { var newDom, arr = []; while(newDOM = dom.nextSibling) { if(newDom.nodeType === 1) { arr.push(newDom); } } return arr; } });
1.2.2 nextAll方法
itcast.fn.extend({ nextAll: function() { var arr = []; itcast.each(this, function(i, v) { itcast.push.apply(arr, itcast.nextAll(v)); }); return itcast(arr); } });
3、借用 Sizzle.js 增强框架
- 目标:使用 Sizzle 增强框架的选择功能
- 思路:对外公开 select 函数,并使用 Sizzle 替换 select
3.1 借用 Sizzle 代码实现
- 思路:框架内部对外公开 select 方法
itcast.extend({ select: select }); // 使用 Sizzle 替换 select itcast.select = Sizzle;
4、事件模块
4.1 回顾原生事件
- 问题:常用DOM事件有哪些?
onclick / onmouseenter / onmouseleave / onmouseover / onmouseout onkeydown / onkeyup / onfocus / onblur on...
4.2 事件的相关概念
- 目标:回顾事件的相关知识点
4.2.1 事件的三部分
- 1 事件类型(名称)
- "click"、"mouseenter"、"mouseleave"
- 2 事件目标
- 被绑定事件的对象
- 3 事件处理程序
- 事件发生时,处理或响应事件的函数
4.2.2 事件对象和事件传播
- 解释:与特定事件相关且包含有关该事件详细信息的对象
- 事件传播:
- 1 冒泡(由内到外)
- 2 捕获(由外到内)-> true
4.3 注册事件
4.3.1 方式一:"on" + 事件名
- 优势:适用于所有浏览器的常用事件类型
- 劣势:最多只能绑定一个事件
dv.onclick = function() { };
4.3.2 方式二:设置HTML标签属性
- 劣势:HTML内容与JavaScript混杂在一起,并让维护变的困难
<button onclick="alert(‘划船不用桨‘);"></button> <button onclick="fn();"></button> <script> function fn() { alert("划船不用桨"); } </script>
4.3.3 方式三:addEventListener()
- 优势:可以绑定同一个事件多次,事件调用顺序跟注册顺序相同
// 参数一:事件名 // 参数二:事件处理程序 // 参数三:false表示冒泡,true表示捕获 dv.addEventListener("click", function() {}, false);
4.3.4 IE的事件 attachEvent() (IE9以下的浏览器)
- 不支持捕获
- 注意:事件类型需要带"on"
// 参数一:事件名 // 参数二:事件处理程序 dv.attachEvent("onclick", function() {});
5、创建绑定事件方法
- 目标:给框架添加绑定事件的方法,实现添加事件的功能
5.1 添加 click 方法
- 目标:实现绑定单击事件的功能
- 问题:使用赋值操作存在覆盖的问题
itcast.fn.extend({ click: function(callback) { this.each(function() { this.onclick = callback; }); } });
5.2 修改 click 方法
- 目标:给同一个元素添加多次 click 事件
- 思路:使用W3C标准事件绑定方式
itcast.fn.extend({ click: function(callback) { this.each(function() { this.addEventListener("click", callback); }); return this; } });
5.3 添加 on 和 off 方法
- 目标:给框架添加事件统一处理方法 on 和 off
itcast.fn.extend({ on: function(type, callback) { this.each(function() { if(this.addEventListener) { this.addEventListener(type, callback); } else { this.attachEvent("on" + type, callback); } }); return this; }, off: function() { this.each(function() { if(this.removeEventListener) { this.removeEventListener(type, callback); } else { this.detachEvent("on" + type, callback); } }); return this; } });
5.4 添加 mouseenter 方法
- 目标:实现绑定鼠标进入事件的功能
- 问题:还有很多其他事件,也需要每个都这样添加吗?
itcast.fn.extend({ mouseenter: function(type, callback) { return this.on("mouseenter", callback); } });
5.5 添加绑定普通事件的方法
- 目标:统一添加所有普通事件绑定方法
- 优势:管理和维护方便,最终调用on方法统一绑定事件方法
itcast.each(("click,mouseenter,mouseleave,keydown,keyup").split(","), function(i, v) { itcast.fn[v] = function(callback) { return this.on(v, callback); }; });
6、扩展:事件对象 - 事件处理程序的参数
- 解释:事件对象的属性提供了有关事件的详细信息
- 说明:事件对象会因为事件类型不同而不同
6.1 访问事件对象
- 目标:兼容浏览器实现获取事件对象
- 差异:
1 普通事件绑定方式(如 onclick=..): W3C标准:使用事件处理程序参数(event)IE9+ / Chrome / FF IE(8及以下版本)中 :使用 window.event 2 addEventListener 和 attachEvent 都实现了事件参数event 说明:即使是都实现了事件参数event,但是对象中的一些属性值还是存在差异, 例如:which IE: button 左1 中4 右2 which 不存在 Chrome: button 左0 中1 右2 which 左1 中2 右3
6.1.1 关于 attachEvent 的浏览器兼容情况
attachEvent的兼容性: 支持: IE6 - IE10 不支持: IE11+(支持 addEventListener)
6.2 事件对象的兼容
- 思路:使用逻辑中断,
e = e || window.event;
6.3 框架中使用事件对象
itcast("div").click(function(e) { e = e || window.event; // 获取事件类型 alert(e.type); });
itcast("div").click(function(e) { alert(e.which); });
7、实现 hover 和 toggle 函数
7.1 实现hover
- 目标:鼠标进入执行第一个事件,鼠标离开执行第二个事件
7.1.1 演示jQuery中的hover方法
- 说明:jQuery中的hover方法内部使用mouseenter和mouseleave实现
$("div").hover(function() { $(this).css("background", "#abc"); }, function() { $(this).css("background", "#fff"); });
7.1.2 添加 hover 函数
itcast.fn.extend({ hover: function(fn1, fn2) { return this.mouseenter(fn1).mouseleave(fn2); } });
8、入口函数
- 目标:让核心函数 itcast 支持文档加载完成事件
8.1 onload 和 addEventListener
if(itcast.isFunction(selector)) { // window.onload = selector; window.addEventListener("load", selector); }
8.2 解决调用顺序问题
- 目标:不同浏览器中onload事件执行顺序相同
8.2.1 使用数组存储事件
var eventList = []; window.onload = function() { for(var i = 0; i < eventList.length; i++) { eventList[i](); } }; if(itcast.isFunction(selector)) { eventList.push(selector); }
8.2.2 保存当前事件
if(itcast.isFunction(selector)) { var oldFunc = window.onload; if(typeof oldFunc === "function") { window.onload = function() { selector(); oldFunc(); }; } else { window.onload = selector; } }
9、移除事件
- 注意:只能移除绑定的事件
var fn = function() { alert(123); }; dv.addEventListener("click", fn); dv.removeEventListener("click", fn);
时间: 2024-10-14 04:55:12