首先看一下DOM树:
当我们点击一个事件的时候,其触发了连接元素的单击事件,该事件则引发任何我们已经绑定到该元素的单击事件上的函数的执行。
例如:
$('a').bind('click',function(){
alert("hello world");
})
click事件接着会向树的根方向传播最终会传播到window对象,
在操纵DOM的语境中,document是根节点。
1:.bind()事件
如上例所示,jQuery扫描文件找出所用的$('a')元素,并把alert函数绑定到每个元素的click事件上。
2:.live()事件
如:$('a').live('click',function(){
alert('hello world');
})
JQuery把alert函数绑定到$(document)元素上,并使用’click’和’a’作为参数。任何时候只要有事件冒泡到document节点上,它就查看该事件是否是一个click事件,以及该事件的目标元素与’a’这一CSS选择器是否匹配,如果都是的话,则执行函数。
live方法还可以被绑定到具体的元素(或“context”)而不是document上,像这样:
可以注意到,这一过程与.live()类似,但是其把处理程序绑定到具体的元素而非document这一根上。精明的JS’er们可能会做出这样的结论,即$('a').live() == $(document).delegate('a'),是这样吗?嗯,不,不完全是。
现在用的比较多的就是on了
通过查看jQuery的源代码(我查看的版本是1.12.4),可以发现无论bind()还是delegate()都是通过on()方法实现的,只是参数不同,如下图:
直接绑定和事件委托
1:直接绑定:大多数浏览器的事件冒泡,都是从文档的最深、最内层发生事件的元素(也称为event target——事件目标),一路向上到达body或document元素上。在IE8和之前的版本上,少数事件例如change、submit不支持原生的事件冒泡,但jQuery模拟并创建了一致的、跨浏览器的事件冒泡行为。
如果on()方法的selector
参数为空,事件处理程序就被称为直接绑定。每当在被绑定元素上(如下例中被绑定的document元素,译者注)发生事件时,无论这个事件发生在这个元素上还是从内层元素经冒泡而来,该处理程序都会被调用。
并且,如果on()方法的selector
参数为空,它与bind()方法相同——只能绑定页面已有元素的事件。
下面我们用代码说明什么是直接绑定:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
页面执行效果如下图:
如果on()方法的
selector
参数不为空,事件处理程序就被称为委托。当事件直接发生在被绑定的元素上(如下例中绑定到document上,译者注)时,该程序不会被调用,而只有当事件发生在与选择器匹配的内部元素上(如下例中click事件发生在button上,译者注)时,才会调用该程序。
jQuery的事件委托是将事件从事件的发生者(即event target,译者注)一直向上冒泡到绑定了事件处理程序的元素上(例如从最内层元素向上冒泡到最外层元素),并为冒泡“沿路”过程中匹配的所有选择器执行事件处理程序。
下面我们用代码说明什么是委托:
- 1
- 2
- 3
- 4
- 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次。
- 1
- 2
- 3
事件委托方式(如下代码)是将事件处理程序绑定到一个元素上,即tbody
上,事件只需向上冒泡一级(从被点击的tr
元素到tbody
元素)。事件只需绑定一次,然后采用事件冒泡来触发事件。
- 1
- 2
- 3
以上内容翻译自:http://api.jquery.com/on/ 《Direct and delegated events》一节
总结
1.选择器匹配到的元素比较多时,不要用bind()迭代绑定
2.用id选择器时,可以用bind()
3.需要给动态添加的元素绑定时,用delegate()或者on()
4.用delegate()和on()方法,dom树不要太深
5.尽量使用on()来代替delegate()和bind()
6.在需要为较多的元素绑定事件的时候,优先考虑事件委托,可以带来性能上的好处
7.bind()和delegate()都是通过on()方法实现的,只是参数不同——当on()的selector参数为空时,其效果完全等同于bind();当selector参数不为空时,其效果完全等同于delegate();
8.使用.on()方法时,事件只会绑定到$()函数的选择符表达式匹配的元素上(上面例子中,为了简单绑定到了document),因此可以精确地定位到页面中的一部分,从而减少事件冒泡的开销。
停止传播
最后一个我想做的提醒与事件传播有关。通常情况下,我们可以通过使用这样的事件方法来终止处理函数的执行:不过,当我们使用live或是delegate方法的时候,处理函数实际上并没有在运行,需要等到事件冒泡到处理程序实际绑定的元素上时函数才会运行。而到此时为止,我们的其他的来自.bind()的处理函数早已运行了。
原文出处: 点击打开链接