jQuery 的事件绑定与事件委托
DOM 树
在操纵DOM的语境中,document是根节点。
事件冒泡
当我们点击⼀个a链接时,其触发了链接元素的单击事件,该事件会引发所有已绑定到该元素的单击事件上的函数的执⾏——这就是事件触发
如下代码,⼀个⽤户单击操作会触发alert函数的执⾏。
⽽在上图执⾏之后,click事件会接着向树的根⽅向传播,⼴播到⽗元素,然后是每级的祖先元素,只要是它的某个后代元素上的单击事件被触发,事件就会传给它————这就是事件冒泡
官⽅说明
明⽩了事件冒泡的概念,我们正式进⼊的事件绑定与事件委托(也成事件代理)的讲解中。
⾸先我们从jQuery的官⽹上看⼀下关于这4个⽅法的说明:
live():jQuery1.7之后弃⽤ (故本⽂不再讲解这个⽅法) bind(): 动态添加的元素⽆法使⽤该⽅法绑定事件 delegate():jQuery1.7之后被on()取代 on(): jQuery1.7之后引⼊,⽀持事件绑定的全部功能。
此外,jQuery官⽹上还说明的⼀点是:
翻译过来就是:
在IE8和之前的版本中,少数事件如change、submit不⽀持原⽣的事件冒泡,但是jQuery为它们模拟了事件冒泡以此创建了⼀致的、跨浏览器的⾏为。
换句话说:jQuery模拟了所有的事件冒泡,使所有事件到⽀持事件冒泡并兼容所有浏览器。
bind
bind()的⽤法
bind()的⽤法如下: 在⽤jQuery 的事件绑定时,会⽤到on()、bind()、live()、 delegate()这⼏个⽅法,但对他们的区别缺从未注意过,现稍总结⼀下,如有错误,欢迎指正。1$('a').bind('click', function () { alert("That tickles!") });
1
jquery源码在线bind()存在的问题
我们⽤⼀个能够看出bind()问题的代码来说明
这段代码的作⽤是:扫描整个html⽂档出所有的$(‘div’)元素,并把alert函数绑定到每个元素的click事件上。
从这个代码中,我们可以发现bind()有如下问题:
delegate
上述bind()的前2个问题,⽤delegate可以解决。
delegate()的⽤法
delegate()的⽤法如下: 这段代码的作⽤是:扫描⽂档查$(‘#container’),并使⽤click事件和’a’这⼀CSS选择器作为参数把alert函数绑定
到$(‘#container’)上。任何时候只要有事件冒泡到$(‘#container’)上,它就查看该事件是否是click事件,以及该事件的⽬标元素是否与CCS选择器(即’a’元素)相匹配。如果两种检查的结果都为真的话,它就执⾏函数。
delegate()的特点
使⽤delegate()⽽不是bind()的原因
1、为了把处理程序附加到可能还未存在于DOM中的DOM元素之上。因为bind是直接把处理程序绑定到各个元素上,它不能把处理程序绑定到还未存在于页⾯中的元素之上。
2、如果你运⾏了$(‘a’).bind(…),⽽后新的链接经由AJAX加⼊到了页⾯中,则你的bind处理程序对于这些新加⼊的链接来说是⽆效的。⽽另⼀⽅⾯delegate则是被绑定到另⼀个祖先节点上,因此其对于任何⽬前或是将来存在于该祖先元素之内的元素都是有效的。
3、或者为了把处理程序附加到单个元素上或是⼀⼩组元素之上,监听后代元素上的事件⽽不是循环遍历并把同⼀个函数逐个附加到DOM中的100个元素上。把处理程序附加到⼀个(或是⼀⼩组)祖先元素上⽽不是直接把处理程序附加到页⾯中的所有元素上,这种做法带来了性能上的好处。
on //绑定单个事件$( "#foo" ).bind( "click", function () { alert( "User clicked on 'foo.'" );});//绑定多个事件$( "#foo" ).bind( "mouseenter mouseleave", function () { $( this ).toggleClass( "entered" );});
1
2
3
4
5
6
7
8$("div").bind("click", function () { alert($(this ).text()); })
1
2
3 1、这⾥⽤到了隐式迭代,如果匹配到的元素特别多的时候,⽐如页⾯中有100个div 元素,就得执⾏绑定100次。对于⼤量元素来说,影响到了性能。但是如果 2、bind()只能给调⽤它的时候已经存在的元素绑定事件,对于动态添加的元素⽆法使⽤该⽅法绑定事件。 3、官⽹建议使⽤on()来替代bind()
1
2
3$('#container').delegate('a', 'click', function () { alert("That tickles!") });
1 1、直接将⽬标元素选择符("a")、事件("click")及处理程序与“委托⽅”$("#container")绑定,不额外收集元素、事件传播路径缩短、语义明确; 2、⽀持链式调⽤,即⽀持如$("table").find("#info").delegate(...)的代码来精确控制; 3、使⽤事件委托时,如果注册到⽬标元素上的其他事件处理程序使⽤.stopPropagation()阻⽌了事件传播,那么事件委托就会失效。
1
2
3
通过查看jQuery的源代码(我查看的版本是1.12.4),可以发现⽆论bind()还是delegate()都是通过on()⽅法实现的,只是参数不同,如
下图:
on()的官⽅API描述如下:
官⽹建议从jQuery1.7开始,尽量使⽤on()⽅法来绑定事件,可以不必再使⽤delegate()或bind()⽅法了。
直接绑定和事件委托
我们直接看官⽹对直接绑定和事件委托的介绍
⼤多数浏览器的事件冒泡,都是从⽂档的最深、最内层发⽣事件的元素(也称为event target——事件⽬标),⼀路向上到达body 或document元素上。在IE8和之前的版本上,少数事件例如change、submit不⽀持原⽣的事件冒泡,但jQuery模拟并创建了⼀致的、跨浏览器的事件冒泡⾏为。
如果on()⽅法的selector 参数为空,事件处理程序就被称为直接绑定。每当在被绑定元素上(如下例中被绑定的document元素,译者注)发⽣事件时,⽆论这个事件发⽣在这个元素上还是从内层元素经冒泡⽽来,该处理程序都会被调⽤。
并且,如果on()⽅法的selector 参数为空,它与bind()⽅法相同——只能绑定页⾯已有元素的事件。
下⾯我们⽤代码说明什么是直接绑定:
.on( events [, selector ] [, data ][, handler])
1
页⾯执⾏效果如下图: 如果on()⽅法的selector 参数不为空,事件处理程序就被称为委托。当事件直接发⽣在被绑定的元素上(如下例中绑定到
document上,译者注)时,该程序不会被调⽤,⽽只有当事件发⽣在与选择器匹配的内部元素上(如下例中click事件发⽣在button 上,译者注)时,才会调⽤该程序。
jQuery的事件委托是将事件从事件的发⽣者(即event target,译者注)⼀直向上冒泡到绑定了事件处理程序的元素上(例如从最内层元素向上冒泡到最外层元素),并为冒泡“沿路”过程中匹配的所有选择器执⾏事件处理程序。
下⾯我们⽤代码说明什么是委托:</div ><script type ="text/javascript"> $(function (){ //将click 事件绑定在document 对象上, //页⾯上任何元素发⽣的click 事件都冒泡到document 对象
上得到处理 //从⽽调⽤事件处理程序 //本例为了简单绑定到了document ,实际上绑定到那个元素上都有类似效果 $(document).on("click",function (e){ console.log(e.target.tagName + " is clicked") }) }) </script ></body >
5
6
7
8
9
10
11
12
13
14
15
16
17
⾯执⾏效果如下图: 事件处理程序只会被绑定到当前已被选定的元素上(如上例中的document元素上,译者注),这些元素在调⽤on()⽅法时必须已经存在——同bind()。
为了确保这些元素已经存在并能被选中,请将代码放置到</body>标签之前或者在$(function(){ ... })内执⾏事件绑定。或者,使⽤事件委托来绑定事件处理程序。
事件委托的优点
1、能处理来⾃于内层⼦元素的事件,这些内层⼦元素是在稍后时间⾥被添加的⽂档中的。通过选择⼀个在绑定事件委托处理程序时肯定存在的元素,就可以使⽤事件委托来避免 需要频繁的添加和删除事件处理程序的操作。 这个元素可以是MVC模式下的⼀个视图容器元素或者是document元素(如果事件处理程序需要监听⽂档中的全部冒泡事件)。在加载任何html代码之前,document 元素已经在html⽂档的头部存在了,所以⽆需等待dom ready就可以在document这个元素上绑定事件了,这是安全可靠的。
2、除了可以处理尚未创建的内层⼦元素的事件,事件委托的另⼀个优点是:当需要监听很多元素时,事件委托的性能更好。例如:有⼀个1000⾏数据的表格,下⾯的代码就是将⼀个事件处理程序绑定到这1000个元素上,事件绑定需要执⾏1000次。 事件委托⽅式(如下代码)是将事件处理程序绑定到⼀个元素上,即tbody 上,事件只需向上冒泡⼀级(从被点击的tr 元素到tbody 元素)。事件只需绑定⼀次,然后采⽤事件冒泡来触发事件。 </div > <script type ="text/javascript"> $(function (){ //将click 事件绑定在document 对象上, //并传⼊第⼆个可选参数:selector //当事件冒泡到document 对象时,检测事件的target , //如果与传⼊的选择符(这⾥是button )匹配,就调⽤事件处理程序即触发事件,否则不触发。 $(document).on("click","button",function (e){ console.log(e.target.tagName + " is clicked") }) }) </script > </body >
5
6
7
8
9
10
11
12
13
14
15
16
17$( "#dataTable tbody tr" ).on( "click", function () { console.log( $( this ).text() );});
1
2
3
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论