章节
问答
课签
笔记
评论
占位
占位

几种绑定

采用事件委托最直观的感受就是,不需要给每一个指定的元素绑定事件,从而降低了繁琐的绑定过程,节约了代码量,同时也节约了内存的开销。绑定一个事件都是需要占用内存消耗的,除了性能的差异,通过委托的事件还能很友好的支持动态绑定,只要 on 的 delegate 对象是 HTML 页面原有的元素,由于是事件的触发是通过 Javascript 的事件冒泡机制来监测,所以对于所有子元素(包括后期通过 JS 生成的元素)所有的事件监测均能有效,且由于不用对多个元素进行事件绑定,能够有效的节省内存的损耗。

那么 jQuery 对事件的绑定分别有几种 API,具体有什么区别我们来了解一下:

bind方法

.bind()方法用于直接附加一个事件处理程序到元素上,处理程序附加到 jQuery 对象中当前选中的元素,所以在 .bind() 绑定事件的时候这些元素必须已经存在,很明显就是直接调用没利用委托机制。

live方法

将委托的事件处理程序附加到一个页面的 document 元素,从而简化了在页面上动态添加的内容上事件处理的使用。

例如:

$('a').live('click', function() { alert("!")})

JQuery 把 alert 函数绑定到 $(document) 元素上,并使用 ’click’和 ’a’作为参数。任何时候只要有事件冒泡到 document 节点上,它就查看该事件是否是一个 click 事件,以及该事件的目标元素与’a’这一CSS 选择器是否匹配,如果都是的话,则执行函数。

因为更高版本的 jQuery 提供了更好的方法,没有 .live() 方法的缺点,所以 .live() 方法不再推荐使用,特别是使用 .live() 出现的以下问题:

  1. 在调用 .live() 方法之前,jQuery 会先获取与指定的选择器匹配的元素,这一点对于大型文档来说是很花费时间的。
  2. 不支持链式写法。例如,$("a").find(".offsite, .external").live( ... ); 这样的写法是不合法的,并不能像期待的那样起作用。
  3. 由于所有的 .live() 事件被添加到 document 元素上,所以在事件被处理之前,可能会通过最长最慢的那条路径之后才能被触发。
  4. 在移动 iOS (iPhone, iPad 和 iPod Touch) 上,对于大多数元素而言,click 事件不会冒泡到文档 body 上,并且如果不满足如下情况之一,就不能和 .live() 方法一起使用:使用原生的可被点击的元素,例如, a 或 button,因为这两个元素可以冒泡到 document。
  5. 在 document.body 内的元素使用 .on() 或 .delegate() 进行绑定,因为移动 iOS 只有在 body 内才能进行冒泡。
  6. 需要 click 冒泡到元素上才能应用的 CSS 样式 cursor:pointer (或者是父元素包含document.documentElement)。但是依然需要注意的是,这样会禁止元素上的复制/粘贴功能,并且当点击元素时,会导致该元素被高亮显示。
  7. 在事件处理中调用 event.stopPropagation() 来阻止事件处理被添加到 document 之后的节点中,是效率很低的,因为事件已经被传播到 document 上。
  8. .live() 方法与其它事件方法的相互影响是会令人感到惊讶的。例如,$(document).unbind("click") 会移除所有通过 .live() 添加的 click 事件!
     

delegate方法

为了突破单一 .bind() 方法的局限性,实现事件委托,jQuery 1.3引入了.live()方法。后来,为解决“事件传播链”过长的问题,jQuery 1.4又支持为 .live() 方法指定上下文对象。而为了解决无谓生成元素集合的问题,jQuery 1.4.2干脆直接引入了一个新方法 .delegate()

使用 .delegate(),前面的例子可以这样写:

$('#element).delegate('a', 'click', function() { alert("!!!") });

jQuery 扫描文档查找(‘#element’),并使用 click 事件和’a’这一CSS选择器作为参数把 alert 函数绑定到(‘#element)上。

任何时候只要有事件冒泡到$(‘#element)上,它就查看该事件是否是click事件,以及该事件的目标元素是否与CCS选择器相匹配。如果两种检查的结果都为真的话,它就执行函数。

可以注意到,这一过程与.live()类似,但是其把处理程序绑定到具体的元素而非document这一根上。

那么 (′a′).live()==(document).delegate('a') ?

可见,.delegate() 方法是一个相对完美的解决方案。但在DOM结构简单的情况下,也可以使用.live()。

on方法

其实 .bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate()也是一样的都是通过.off()来实现的,提供了一种统一绑定事件的方法。

总结:

在下列情况下,应该使用 .live()或 .delegate(),而不能使用 .bind():

1. 为DOM中的很多元素绑定相同事件;
2. 为DOM中尚不存在的元素绑定事件;
3. 用.bind()的代价是非常大的,它会把相同的一个事件处理程序hook到所有匹配的DOM元素上
4. 不要再用.live()了,它已经不再被推荐了,而且还有许多问题
5. .delegate()会提供很好的方法来提高效率,同时我们可以添加一事件处理方法到动态添加的元素上

我们可以用 .on() 来代替上述的 3 种方法。

不足点也是有的:

1. 并非所有的事件都能冒泡,如load, change, submit, focus, blur
2. 加大管理复杂
3. 不好模拟用户触发事件
4. 如何取舍就看项目实际中运用了

 

任务

?不会了怎么办
||

提问题

写笔记

公开笔记
提交
||

请验证,完成请求

由于请求次数过多,请先验证,完成再次请求

加群二维码

打开微信扫码自动绑定

您还未绑定服务号

绑定后可得到

  • · 粉丝专属优惠福利
  • · 大咖直播交流干货
  • · 课程更新,问题答复提醒
  • · 账号支付安全提醒

收藏课程后,能更快找到我哦~

使用 Ctrl+D 可将课程添加到书签

邀请您关注公众号
关注后,及时获悉本课程动态

举报

0/150
提交
取消
全部 精华 我要发布
全部 我要发布
最热 最新
只看我的

手记推荐

更多

本次提问将花费2个积分

你的积分不足,无法发表

为什么扣积分?

本次提问将花费2个积分

继续发表请点击 "确定"

为什么扣积分?