前言:
前面几篇都在复习用法,这一篇要回忆一下机制。
大概的一个轮廓是,事件传播机制(事件冒泡,事件捕获,事件对象)和事件委托(事件绑定)。
事件的旅程————事件传播机制
首先再熟悉一遍原生js中的事件传播机制。
这里有一个html结构:
1 | <div class="foo"> |
事件捕获
如果我给a元素绑定了一个click事件,然后我去点击a,此时我的浏览器如果采取的事件传播机制是事件捕获,那么我的事件是从外到里面进来的,就是说如果三个元素上都有事件侦听程序,那么第一个响应的元素是div,第二个响应的元素是bar,最后一个响应事件的才是a元素上的事件监听程序。
这种事件首先交给最外层元素,接着再交给更具体的元素的事件传播过程叫做事件捕获。
事件冒泡
还是这段程序,还是为每个元素都安装事件舰艇程序,我还是去点击a,如果此时我的浏览器采取的是事件冒泡机制,那么事件传播的顺序是a->span->foo。
反过来了!
这种当事件发生时,首先发送给最具体的元素,在这个元素获得响应机会之后,事件向上冒泡到更一般的元素的事件传播机制叫做事件冒泡。
实际应用中的情况
毫不奇怪,不同的浏览器开发者最初采用的是不同的事件传播模型,因此,最终出台的DOM标准规定应该同时使用这两种策略。
首先,事件从一般元素到具体元素逐层捕获。然后事件再通过冒泡返回DOM树的顶层。
而事件处理程序也可以注册到这个过程中的任何一个阶段。
jQuery中的事件传播模型
为了确保跨浏览器的一致性,也为了更让人容易理解。
jQuery始终会在模型的冒泡阶段注册事件处理程序
jQuery中的事件对象
我们可以通过在处理函数中添加一个参数的形式引用事件对象:
1 | $(document).ready(function(){ |
楼上这段程序,传入的event承接了事件对象,这个event名字不唯一,叫什么都行,只要它是事件处理程序中的第一个参数。
利用event对象,我们可以得到事件目标(event.target),还可以利用它来阻止事件冒泡(event.stopPropagation)。
阻止默认操作
有时候浏览器会给我们一些很不讨人喜欢的默认操作。
比如我点一下提交按钮,我想给它自定义一个响应,不让它跳转,而让它按我说的做。然后我为它安装事件处理程序,然后我会发现安装后它仍然会直接跳转,这时候怎么办。
这个跳转,就是浏览器的一个默认操作,我需要阻止它:
1 | event.preventDefault() |
tip: 既想阻止冒泡,又想阻止默认行为,这时候在事件处理函数里面返回一个false就可以了。
jQuery中的事件委托机制
这个比较重要。因为涉及到一个非常重要的方法on。
事件委托是利用事件冒泡的一项高级技术。通过事件委托,可以借助一个元素上的事件处理程序完成很多工作。
想象一个巨大的表格,它里面有一堆小格子,我希望每个小格子被点击时都有事件处理程序来响应它,那我难不成要给成千上万个小格子都安装事件处理程序???
不不不,累死了,毁性能毁内存。
为了解决这个问题,可以只在DOM的一个祖先元素上指定一个单击处理程序,借助事件冒泡,拦截子元素的事件,然后再作出响应。
on()方法
on()方法的常见调用形式:
1 | element.on(事件名, 事件处理程序); |
利用这种形式,我们可以给一个元素安装指定的事件的事件监听程序。
on()方法的事件委托实现:
1 | element.on(事件名, 子元素, 事件处理程序); |
楼上,多出的这个参数,就是事件的委托方,而element是事件的被委托方。
(子元素的传入形式是一个选择符表达式)。
如果on()方法传入的第二个参数是一个选择符表达式,jQuery会把对应的事件处理程序绑定到element对象,同时比较event.target和选择符表达式,如果匹配,jQuery会把this关键字映射到匹配的元素,否则不会执行事件处理程序
off()方法移除事件处理程序
off()方法的用法也比较简单,它是和on()方法呼应的,我们直接看一段demo思路就会比较清晰:
1 | function btnClick1(){ |
结语
jQuery具有良好的跨浏览器运行能力,对于事件传播机制的处理方式验证了这一点。
在jQuery中,不仅有on()方法,还有一个功能类似的delegate()和undelegate()方法。
虽然最重要的也最多用的仍然是on()和off()方法,不过另外两个方法也很有说头,我会另写博客做说明。