jQuery事件与DOM事件的是非纠葛
在javascript和JQuery之中,都有事件的处理方式,在我们编写程序实现某些功能的时候,我们会发现使用原生的DOM事件与JQuery中封装的事件都能实现同样的效果,那么也许我们会认为他们之间的区别不是很大,甚至说基本没有区别。这种观点是错误的,其实在事件函数的底层设计时,他们赋予元素的事件属性是通过不同的事件绑定机制来实现的。
我们先从表面理解:我们都知道,JQuery是javascript的一个函数库,他是基于javascript原生设计的。就是说JQuery中的事件,都是通过javascript来编写的。这是其中的一点;还有最重要的一点就是他们绑定事件的方式不一样,javascript和JQuery中则采用事件机制不同。这是他们之间主要的不同点,接下来我们细细讲讲。
( 一 ) javascript 事件
一 .DOM事件及其传输机制
首先我们要了解的事件的一些知识了,事件的组成,事件有3部分构成的,分别是事件源,事件,和事件处理。事件源和事件是最简本的要求,可也没有处理程序。
1.事件源:
简单的说,就是被绑定事件的元素,
2.事件
在Javascript中event对象中有很多的事件,例如onload,onclick,onmouse等,但是我们知道javascript中有内置的事件和Dom中event的事件,他们中有很多的相同事件,但是DOM对象event对象中相比较多出的很多的键盘/鼠标事件,和一些关于IE的私有事件(仅仅IE能使用)。
3.事件处理
当事件被触发时,所要执行的javascript的代码段,去完成某项功能。可以不添处理程序。
(———)“事件冒泡”
在学习c语言时都知道冒泡排序,“事件冒泡”和它是完全不同的,所谓的事件冒泡就是说,当我们触发事件时,事件会一级级的向它的祖先元素传递,一直到最高级,它的传递顺序对于不同浏览器,也有所不同;
对于IE:触发事件元素——祖先元素——body—— HTML——document;
高级浏览器:触发事件元素——祖先元素——body——document——window;
也就是说事件一开始先从根节点流向目标事件(称为事件捕获),然后在目标事件上被触发(目标阶段),之后再回到文档根节点(事件冒泡)。事件冒泡是很有用的,他能将我们从事件的监听中释放出来,同时我们也可以监听目标事件的祖先元素。又是因为事件冒泡的特点,这样就会造成我们的各个模块之间会相互的影响,所以必须要消除他的影响。
(-----)事件捕获阶段
与事件冒泡不同,事件捕获是事件的第一个阶段,事件从文档根节点出发,随着DOM树向事件目标流去,经过DOM的各个节点,一直流到事件目标位置,事件捕获的主要作用就是建立一个路径,在冒泡阶段,事件会沿着这条路径回到跟节点。
(----)目标阶段
当事件到达目标节点时,事件就进入的目标阶段。事件在目标节点上被触发,然后向上传播,直到回到文档根节点。
清除事件影响,可以通过event对象下的event.stopPropagation()函数来清除,对于IE,使用event.cancelBubble=true;来清除影响。
在说一种清除事件冒泡的办法:preventDefault();这个函数也是event对象的办法,他和stopPropagation()有一些区别的;
preventDefult(),他仅仅阻止事件的处理程序不在执行,却不能阻止冒泡机制,
stopPropagation(),他能阻止冒泡机制,同事不影响事件的处理程序。
二.事件阻止
上面说了对事件的阻止最常见的两种办法,1.preventDefault();2.stopPropagation();我们来细细说说他们的差别
1、preventDefault()
preventDefault()函数是用来阻止浏览器的默认行为,那么什么是浏览器默认行为呢?举个例子,我们一超链接link的<a>标签为例,当我们点击<a>标签时,就触发了浏览器默认click事件,通过冒泡机制,一直传递到document,然后由浏览器解析href内容,并在导航栏中打开地址。
通过preventDefault()函数,我们可以阻止很多浏览器的默认行为,比如敲击空格键的时页面滚动。
2.stopPropagation()
调用event.stopPropagation()只会阻止传播链中后续的回调函数被触发(阻止了冒泡阶段)。它不会阻止事件处理函数的行为。
三. 自定义事件
浏览器并不是能唯一触发dom事件的载体,我们可以创建自定义的事件并把它们分派给你文档中的任意节点。这些自定义的事件和通常的DOM事件有相同的行为。这也就是我们最最常用的绑定事件的方法,比如:li.onclick,div.onmouseover,都是一些常见的自定义事件。
四.代理事件
代理事件监听可以让你使用一个事件监听器去监听大量的DOM节点的事件,在这种情况下,它是一种更加方便并且高性能的事件监听方法。举例来说,如果有一个列表<ul>包含了100个子元素<li>,它们都需要对click事件做出相似的响应,那么我们可能需要查询这100个子元素,并分别为他们添加上事件监听器。这样的话,我们就会产生100个独立的事件监听器。如果有一个新的元素被添加进去,我们也需要为它添加同样的监听器。这种方式不但代价比较大,维护起来也比较麻烦。
代理事件监听可以让我们更简单的处理这种情况。我们不去监听所有的子元素的click事件,相反,我们监听他们的父元素<ul>。当一个<li>元素被点击的时候,这个事件会向上冒泡至<ul>,触发回调函数。我们可以通过检查事件的event.target属性来判断具体是哪一个<li>被点击了。
五 事件监听和移除监听机制
(—):事件监听
在过去,浏览器的事件监听机制是不尽相同的,但是随着浏览器的逐渐的标准化,事件监听机制也相对统一了,但是要是你要监听IE浏览器的话,最好使用一些前端的框架,如jQuery,因为这些前端的框架封装了很好的兼容问题。
事件的监听函数:element.addEventListener(<event-name>, <callback>, <use-capture>);
参数:<event-name> 是我们要监听的事件,他可以是任何Dom的标准事件(click,mousedown,);
参数:<callback> 是一个回调函数,当事件被触发的时候,相应的事件对象和数据,会作为一个参数传递给这个函数。
参数:<event-capture> 这个参数返回布尔值,它用来观测回调函数是否在”事件捕获阶段“被触发,
(二):移除事件监听
我们使用 element.removeEventListener()
方法来移除事件监听;
element.removeEventListener(<event-name>, <callback>, <use-capture>);
但是removeElementListener
有一点需要注意的是:你必须要有这个被绑定的回调函数的引用。简单地调用
element.removeEventListener('click');
是不能达到想要的效果的。也就是说,在移除事件监听时,必须要有回调函数的调用,也就是说匿名函数不能作为回调函数来使用的。
最后我们来说一下DOM事件从被触发到事假结束的全部过程:
对与自定义的事件: 一旦事件被触发,通过事件监听机制,浏览器开始“事件捕获”阶段,到达“目标阶段“ ,然后执行相应函数处理,在通过”冒泡机制“将事件传递给根目录。
而浏览器的默认行为的执行过程与上面的差不多,只不过它是由浏览的默认绑定的函数处理方式来执行的,不会受你的控制。
( 二 )JQuery 事件
其实相对于DOM的事件的绑定系统和原理,JQuery的事件机制是非常的简单的。因为jQuery 是对一些js代码的封装,他在封装的过程中为我们解决了很多的问题,比如最棘手的兼容问题,所以直接使用jQuery框架是非常方便的。
JQuery的事件绑定有两种方式:1.绑定事件,2:触发事件;
1.绑定事件
在jQuery中,他为我们提供了许多诸如click(),形式的API,这种事件就是所谓的绑定事件,这种事件的绑定方式很是僵硬,不灵活。
所以为了实现绑定多个事件,JQuery又提供了on()这种绑定事件的方式,它允许我们同时给对象绑定一个或多个事件。还有一个API,bind()
它也可以绑定一个或多个事件,但是bind()和on()的不同之处就在与;on()只对匹配对象绑定事件,而bind()是对所有的匹配元素绑定事件,所以推荐使用on()的方式;
2.触发事件
trigger() 在每个匹配元素上触发某类事件,同时这个函数也会导致浏览器同名的默认行为的执行,所以在使用时为了不影响其他部分,我们需要返回值为false。这种事件是间接的绑定事件,也就是说,在没有触发之前,并没有事件绑定的。
triggerHandler() 具有trigger()的功能,但是他不会触发浏览器的默认行为;
补充:事件代理
jQuery 提供的api delegates()函数是用来做事件代理。给指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。
jQuery事件解绑
off():用来解除on()方式绑定的事件;
unbind():用来解除bind()方式绑定的事件;
undelegates():用来解除以delegates()方式事件委派任务。
事件的范畴很多,但是我们经常用到的也就那些,只要平时稍加留意学习,总会加深对事件的理解,当中可能会出现一些表述不清的情况,就需要我们去查找资料去参考学习了。
困扰我的问题,总的想办法解决,但是难免出错,欢迎您的斧正
希望大家共同学习 共同进步 共同维护前端的一片天!!!