jQuery事件绑定和委托实例


Posted in Javascript onNovember 25, 2014

本文实例讲述了jQuery事件绑定和委托。分享给大家供大家参考。具体方法如下:

jQuery事件的绑定和委托可以用多种方法实现,on()  、 bind()  、 live()  、 delegate() ,还有one()。
 
有时我们可能会像下面这样绑定一个事件:

$("#div1").click(function() {  

    alert("点击后触发");  

});

上面的事件绑定,我们可以通过多种方式去实现:
 
1. on()

//无数据参数  

$("p").on("click", function(){  

alert( $(this).text() );  

});  

  

//有数据参数  

function myHandler(event) {  

alert(event.data.foo);  

}  

$("p").on("click", {foo: "bar"}, myHandler)

与on()对应的是off(),用来移除事件绑定:

var foo = function () {  

  // code to handle some kind of event  

};  

// ... now foo will be called when paragraphs are clicked ...  

$("body").on("click", "p", foo);  

  

// ... foo will no longer be called.  

$("body").off("click", "p", foo);

off():移除on()进行的绑定
one():只绑定一次。
 
2. bind()

参数:
(type,[data],function(eventObject))
type: 含有一个或多个事件类型的字符串,由空格分隔多个事件。比如"click"或"submit",还可以是自定义事件名。
data:作为event.data属性值传递给事件对象的额外数据对象
 
fn:绑定到每个匹配元素的事件上面的处理函数
 
(type,[data],false)
type:含有一个或多个事件类型的字符串,由空格分隔多个事件。比如"click"或"submit",还可以是自定义事件名。
data:作为event.data属性值传递给事件对象的额外数据对象
 
false: 将第三个参数设置为false会使默认的动作失效。
 
同时绑定多个事件类型:

$('#foo').bind('mouseenter mouseleave', function() {  

  $(this).toggleClass('entered');  

});

同时绑定多个事件类型/处理程序:

$("button").bind({  

  click:function(){$("p").slideToggle();},  

  mouseover:function(){$("body").css("background-color","red");},    

  mouseout:function(){$("body").css("background-color","#FFFFFF");}    

});

你可以在事件处理之前传递一些附加的数据。

function handler(event) {  

  alert(event.data.foo);  

}  

$("p").bind("click", {foo: "bar"}, handler)

通过返回false来取消默认的行为并阻止事件起泡。

$("form").bind("submit", function() { return false; })

bind存在的问题

如果表格中要绑定单击事件的有10列500行,那么查找和遍历5000个单元格会导致脚本执行速度明显变慢,而保存5000个td元素和相应的事件处理程序也会占用大量内存(类似于让每个人亲自站在门口等快递)。

在前面这个例子的基础上,如果我们想实现一个简单的相册应用,每页只显示50张照片的缩略图(50个单元格),用户点击“第x页”(或“下一页”)链接可以通过Ajax从服务器动态加载另外50张照片。在这种情况下,似乎使用.bind()方法为50个单元格绑定事件又可以接受了。

事实却不然。使用.bind()方法只会给第一页中的50个单元格绑定单击事件,动态加载的后续页面中的单元格都不会有这个单击事件。换句话说,.bind()只能给调用它的时候已经存在的元素绑定事件,不能给未来新增的元素绑定事件(类似于新来的员工收不到快递)。

事件委托可以解决上述两个问题。具体到代码上,只要用jQuery 1.3新增的.live()方法代替.bind()方法即可:

$("#info_table td").live("click",function(){/*显示更多信息*/});

这里的.live()方法会把click事件绑定到$(document)对象(但这一点从代码中体现不出来,这也是.live()方法饱受诟病的一个重要原因,稍后再详细讨论),而且只需要给$(document)绑定一次(不是50次,更不是5000次),然后就能够处理后续动态加载的照片单元格的单击事件。在接收到任何事件时,$(document)对象都会检查事件类型和事件目标,如果是click事件且事件目标是td,那么就执行委托给它的处理程序。
 
unbind():移除bind进行的绑定。
 
3. live()

到目前为止,一切似乎很完美。可惜,事实并非如此。因为.live()方法并不完美,它有如下几个主要缺点:
$()函数会找到当前页面中的所有td元素并创建jQuery对象,但在确认事件目标时却不用这个td元素集合,而是使用选择符表达式与event.target或其祖先元素进行比较,因而生成这个jQuery对象会造成不必要的开销;
默认把事件绑定到$(document)元素,如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失;
只能放在直接选择的元素后面,不能在连缀的DOM遍历方法后面使用,即$("#info_table td").live...可以,但$("#info_table").find("td").live...不行;
收集td元素并创建jQuery对象,但实际操作的却是$(document)对象,令人费解。
解决之道
为了避免生成不必要的jQuery对象,可以使用一种叫做“早委托”的hack,即在$(document).ready()方法外部调用.live():

(function($){  

    $("#info_table td").live("click",function(){/*显示更多信息*/});  

})(jQuery);

在此,(function($){...})(jQuery)是一个“立即执行的匿名函数”,构成了一个闭包,可以防止命名冲突。在匿名函数内部,$参数引用jQuery对象。这个匿名函数不会等到DOM就绪就会执行。注意,使用这个hack时,脚本必须是在页面的head元素中链接和(或)执行的。之所以选择这个时机,因为这时候刚好document元素可用,而整个DOM还远未生成;如果把脚本放在结束的body标签前面,就没有意义了,因为那时候DOM已经完全可用了。

为了避免事件冒泡造成的性能损失,jQuery从1.4开始支持在使用.live()方法时配合使用一个上下文参数:

$("td",$("#info_table")[0]).live("click",function(){/*显示更多信息*/});

这样,“受托方”就从默认的$(document)变成了$("#info_table")[0],节省了冒泡的旅程。不过,与.live()共同使用的上下文参数必须是一个单独的DOM元素,所以这里指定上下文对象时使用的是$("#info_table")[0],即使用数组的索引操作符来取得的一个DOM元素。 
 
4. delegate()

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

$("#info_table").delegate("td","click",function(){/*显示更多信息*/});

使用.delegate()有如下优点(或者说解决了.live()方法的如下问题):
直接将目标元素选择符("td")、事件("click")及处理程序与“受拖方”$("#info_table")绑定,不额外收集元素、事件传播路径缩短、语义明确;

支持在连缀的DOM遍历方法后面调用,即支持$("table").find("#info").delegate...,支持精确控制;

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

提示:使用事件委托时,如果注册到目标元素上的其他事件处理程序使用.stopPropagation()阻止了事件传播,那么事件委托就会失效。
 
undelegate(): 移除delegate的绑定

希望本文所述对大家的jQuery程序设计有所帮助。

Javascript 相关文章推荐
文字幻灯片
Jun 26 Javascript
java与javascript之间json格式数据互转介绍
Oct 29 Javascript
jquery在项目中做复选框时遇到的一些问题笔记
Nov 17 Javascript
JQuery1.8 判断元素是否绑定事件的方法
Jul 10 Javascript
javascript通过元素id和name直接取得元素的方法
Apr 28 Javascript
js中不同的height, top的区别对比
Sep 24 Javascript
bootstrap datetimepicker 日期插件在火狐下出现一条报错信息的原因分析及解决办法
Mar 08 Javascript
JavaScript表单即时验证 验证不成功不能提交
Aug 31 Javascript
深入Vue-Router路由嵌套理解
Aug 13 Javascript
vue 实现小程序或商品秒杀倒计时
Apr 14 Javascript
element多个表单校验的实现
May 27 Javascript
Vue vee-validate插件的简单使用
Jun 22 Vue.js
2014最热门的JavaScript代码高亮插件推荐
Nov 25 #Javascript
JS跨域问题详解
Nov 25 #Javascript
javascript 中__proto__和prototype详解
Nov 25 #Javascript
js 加密压缩出现bug解决方案
Nov 25 #Javascript
js Object2String方便查看js对象内容
Nov 24 #Javascript
js的[defer]和[async]属性
Nov 24 #Javascript
使用JavaScript 编写简单计算器
Nov 24 #Javascript
You might like
php向js函数传参的几种方法
2014/08/10 PHP
VPS中使用LNMP安装WordPress教程
2014/12/28 PHP
PHP7 list() 函数修改
2021/03/09 PHP
js 通用javascript函数库整理
2011/08/14 Javascript
javascript学习笔记(六) Date 日期类型
2012/06/19 Javascript
实用的Jquery选项卡TAB示例代码
2013/08/28 Javascript
jquery实现倒计时代码分享
2014/06/13 Javascript
使用jQuery判断IE浏览器版本的代码
2014/06/14 Javascript
jQuery插件Tooltipster实现漂亮的工具提示
2015/04/12 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
2015/09/06 Javascript
jquery 获取select数组与name数组长度的实现代码
2016/06/20 Javascript
浅谈angular2路由预加载策略
2017/10/04 Javascript
vue 指令之气泡提示效果的实现代码
2018/10/18 Javascript
学习使用ExpressJS 4.0中的新Router的用法
2018/11/06 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
使用VScode 插件debugger for chrome 调试react源码的方法
2019/09/13 Javascript
uni-app 支持多端第三方地图定位的方法
2020/01/03 Javascript
为什么JavaScript中0.1 + 0.2 != 0.3
2020/12/03 Javascript
python 切片和range()用法说明
2013/03/24 Python
python二叉树遍历的实现方法
2013/11/21 Python
用Python给文本创立向量空间模型的教程
2015/04/23 Python
在Python的Django框架的视图中使用Session的方法
2015/07/23 Python
基于python(urlparse)模板的使用方法总结
2017/10/13 Python
Pycharm中如何关掉python console
2020/10/27 Python
Python爬虫UA伪装爬取的实例讲解
2021/02/19 Python
python 实现网易邮箱邮件阅读和删除的辅助小脚本
2021/03/01 Python
Linden Leaves官网:新西兰纯净护肤品
2020/12/20 全球购物
Hashtable 添加内容的方式有哪几种,有什么区别?
2012/04/08 面试题
创业者迈进成功第一步:如何写创业计划书?
2014/03/22 职场文书
光棍节联谊晚会活动策划书
2014/10/10 职场文书
执法作风整顿剖析材料
2014/10/11 职场文书
大学生心理健康活动总结
2015/05/08 职场文书
第一节英语课开场白
2015/06/01 职场文书
HTML5页面音频自动播放的实现方式
2021/06/21 HTML / CSS
Redis分布式锁Redlock的实现
2021/08/07 Redis
宫崎骏十大动画电影,宫崎骏好看的动画电影排名
2022/03/22 日漫