jQuery使用(七):事件绑定与取消,及自定事件的实现原理
实例方法:
- on()
- one()
- off()
- trigger()
- hover()
一、绑定事件与jQuery事件委托
- $(selector).eventType(fn);
- $(selector).on(event,childSelector,data,function);
- $(selector).one(event,data,function);
1.jQuery可以直接通过点击内置事件类型方法来添加事件程序,比如添加点击事件:$("...").click(function(){console.log(“点我”);});
2.on()方法绑定事件处理程序:
参数 | 说明 |
event |
必需。规定要从被选元素移除的一个或多个事件或命名空间。 由空格分隔多个事件值,也可以是数组。必须是有效的事件。 |
childSelector | 可选。规定只能添加到指定的子元素上的事件处理程序(且不是选择器本身,比如已废弃的 delegate() 方法)。 |
data | 可选。规定传递到函数的额外数据。 |
function | 可选。规定当事件发生时运行的函数。 |
3.这里展示一下不常见的添加多个事件程序:
//html <p>Move.</p> //css .intro{ font-size:150%; color:red; } //js--toggleClass()方法对添加和移除被选元素的一个或多个类进行切换。 $("p").on("mouseover mouseout",function(){ $("p").toggleClass("intro"); });
4.当然也可以给同一个事件绑定多次,与addEventListener()的元素js方法一致。
5.当不指定给子元素绑定事件时,有需要给事件函数传入更多数据的话可以采用对象的方式传入,这样第二个参数就不会被识别为选择器了。(更简单的方式就是直接给第二个参数写一个逗号,不传入参数)
6.jQuery事件委托:
//html <ul> <li>0</li> ...省略n个li <li>n+1</li> </ul> //js $("ul").on("click",function(e){ alert( $(e.target).text() ); });
但是在事件委托有时候会存在一些问题,以上面示例来说,比如不希望点击事件在ul上触发,那么这时候第二个参数就发挥作用了:
$("ul").on("click","li",function(e){ alert( $(e.target).text() ); });
通过以上的修改后,依旧保持事件委托状态,但是点击ul时,事件不会执行,而点击li依然可以正常执行。
7.关于一次事件(one())绑定的应用:
- 有需求是第一次点击a标签跳转淘宝,以后点击都跳转百度
//html <a href="https://www.baidu.com" target="_blank">jump</a> //js $("a").one("click",function(e){ window.open("https://www.taobao.com"); //阻止第一次点击跳转到百度(下面两个操作都可以实现) //return false; e.preventDefault(); });
8.同时给一个dom添加多个事件程序
//html <div class="demo" style="width: 100px;height: 100px;background-color: red;"></div> //js $(".demo").on({ click:function(){ console.log('click'); }, mouseenter:function(){ console.log('mouseenter'); }, mouseleave:function(){ console.log('mouseleave'); } });
二、解除事件程序
- jQuery.off()
- jQuery.off(eventType)
- jQuery.off(eventType,fun)
- jQuery.off(eventType,daughter,fun)
//html <div class="demo" style="width: 100px;height: 100px;background-color: red;"></div> //js function eventOne(){ console.log("eventOne"); } function eventTwo(){ console.log("eventTwo"); } $(".demo").on('click',eventOne); $(".demo").on('click',eventTwo); $(".demo").on('mouseenter',eventOne); $(".demo").off();//解除demo所有事件的事件程序,包括默认事件 $(".demo").off("click");//解除demo的点击事件的所有事件程序 $(".demo").off("click",eventOne);//解除demo的点击事件的eventOne事件程序
在事件委托的事件处理程序绑定时,有指定事件程序只在后辈元素上才有效执行,在绑定事件的元素上不会被触发的一种绑定方式,看示例:
//html <ul> <li>0</li> ...省略n个li <li>n+1</li> </ul> //js
$("ul").on("click","li",function(e){
alert( $(e.target).text() );
});
这种绑定方式实质上就是将事件绑定在ul上,所以解绑事件程序还是解绑ul的事件程序:
$("ul").off("click");
$("ul").off("click","li");//这种方式也没问题
$("ul").off("click","li",fun);//为了程序的可读性,怎么绑定就怎么解除是最规范的写法
当然上面的事件程序是函数表达式不能指定实现指定函数解绑了。
三、主动触发事件程序方法(trigger)及实现原理
- $(selector).trigger(event,param1,param2,...)
- 使用说明:
参数 | 说明 |
event | 必需。规定指定元素上要触发的事件。可以是自定义事件,或者任何标准事件。 |
param1,param2,... |
可选。传递到事件处理程序的额外参数。额外的参数对自定义事件特别有用。 也可以写成数组方式传入[param1,param2,...] |
一个简单的trigger示例代码:
//html <div class="demo" style="width:100px; height:100px; background-color:red;"></div> //js $(".demo").on("click", function(a,b,c,d){ console.log(a,b,c,d); }); $(".demo").trigger("click",[10,20,30,40]);
常见的trigger()使用场景“首次加载倒数广告图层”,当倒数到零时自动取消广告图层,也可以在没有到达零秒之前人为点击取消广告。
(时间紧迫,本想封装一个完整的功能的,有时间再来实现了!)
-
jQuery.on()的自定义事件
-
trigger与自定义事件实现原理
把on的自定义事件放到这部分来分析,绝对不是前面忘记了,想必聪明的你已经想到了,自定义方法没有触发机制,所以必须要trigger()方法来帮助自定义事件触发事件程序。先来看一个简单的自定义事件示例:
//定义自定义事件pageLoad $(".demo").on("pageLoad",function(){ console.log("我的第一个jQuery自定义事件"); });
//trigger触发pageLoad事件
$(".demo").trigger("pageLoad");
应用之简单是吧,好友没有撸源码了,来一波。
咳咳,我得纠正一下态度,绝不是因为它简单我就欺负它,而是大有用途,后期会基于jQuery模仿封装一个自己的fullPage插件,会大量的使用到自定义事件,所以觉得在这里有必要对jQuery自定义事件的原理及trigger的原理有深入的理解。(偷偷告诉你,自定义机制和触发事件机制在初级和中级前端面试中被提问的几率很高哦,中级和高级前端面试中常被提问的Event模块其内部思想非常类似)
//自写jQuery源码部分 //--on()--仅封装自定义事件(内部事件后期再补充) //参数:type -- 事件类型; handle -- 事件触发程序 jQuery.prototype.myOn = function(type,handle){ //遍历jQuery对象的所有DOM for(var i = 0; i < this.length; i++){ //给每个DOM上添加cacheEvent,用来保存每个DOM添加的事件类型 if( !this[i].cacheEvent ){ this[i].cacheEvent = {}; } //每个DOM的每个事件类型(cacheEvent[type])上可以存储多个事件处理函数 if( !this[i].cacheEvent[type] ){ //第一次添加该事件类型时,直接将事件处理函数作为数组元素添加到该事件类型下 this[i].cacheEvent[type] = [handle]; }else{ //如果有该事件类型,并且有值,就将事件函数添加到数组后面 this[i].cacheEvent[type].push(handle); } } } //--trigger事件触发 //参数:type -- 事件类型 jQuery.prototype.myTrigger = function(type){ var self = this; //获取事件程序需要的参数 -- 兼容序列化和数组两种方式传入 var params = arguments.length > 1 ? (Object.prototype.toString.call(arguments[1]) == "[object Array]" ? arguments[1] : [].slice.call(arguments,1) ) : []; //遍历jQuery对象的所有DOM for(var i = 0; i < this.length; i++){ //判断是否含有指定的事件类型 if( this[i].cacheEvent[type] ){ //遍历并执行DOM上指定事件类型的所有函数 -- ele函数 //由于forEach内执行事件程序是this指向window,所以需要self this[i].cacheEvent[type].forEach(function(ele,index){ ele.apply(self,params); }); } } } //测试代码 <div class="demo" style="width: 100px; height: 100px; background-color: red;"></div> <script type="text/javascript" src="MyjQuery.js"></script> <script type="text/javascript"> $(".demo").myOn("pageLoad",function(a,b,c){ console.log("trigger成功"+ a + b + c ); }); $(".demo").myTrigger("pageLoad",10,20,30); $(".demo").myTrigger("pageLoad",["中","国","人"]); </script>
全部jQuery源码等总结完jQuery使用系列博客后会在相关博客上传。
四、hover()
其实hover这个方法非常的简单,而且经常使用,这个方法同等于mouseenter和mouseleave,这种操作非常贴合交互行为,鼠标移入必然就会有移出,如果在这两个状态下需要对行为作出反应,这个方法就再合适不过了,下面就写一个同等对比示例代码:
$(".demo").on("mouseenter",function(){ consoel.log("enter"); }).on("mouseleave",function(){ consoel.log("leave"); }); //haver同等代码 $(".demo").hover(function(){ console.log("enter"); },function(){ console.log("leave"); });
但是hover并不是最友好的交互选择,因为连续的鼠标移入移出会出现抖动,因为事件被触发后会被放到执行队列,会把所有移入移出行为触发的事件都执行,所以对交互体验有一定要求的功能慎用。