一个专注于技术的IT男
翻译
你应该使用的20个有用的jQuery方法
四 15th
原文地址:20 Helpful jQuery Methods you Should be Using
原文作者:Andrew Burgess
这篇文章介绍了jQuery中有用的20个方法,1-20编号如下,本文没有对照原文逐句翻译,这个20个方法名称,我其实就是用下面第14个map()的方式取出来的,亮点如下,firebug真是个离不开的好工具。
说到工具,那就顺便再提一下一个简洁的jQuery代码调试工具:jQueryPad
支持代码高亮,不支持代码辅助,小问题是这个工具带的jQuery.js的版本旧了,需要自己更新一份到它的目录。
(当然,我还是最喜欢firebug,特别是网页复杂的时候)
1 after() / before()
这个无需多说了,上面的图就是个例子,就是在当前对象的前面或者后面插入内容,被插入的内容是当然对象的兄弟节点
2 change()
和click()或者hover()一样,它也是个事件处理器,这个change事件作用于 textarea, text input, select, 当目标元素的值改变的时候触发该事件。它不同于对象失去焦点时触发的事件foucusOut()和blur()。
change()事件对于客户端验证的任务最适合不过了,因为你不需要在输入字段值没有变化的时候重新验证字段。
$(document).ready(
function() {
$('input[type=text]').change(function () {
switch (this.id) {
/* some validation code here */
case "name":
alert(this.value+"....");
break;
default:
alert(this.id);
break;
}
});
});
// HTML Form
Name: <input id="name" type="text"/>
3 Context
在jQuery中,使用选择器,其实默认作用于document这个上下文上
了解了这一点话,Context就简单了,它是一个属性兼参数
作为属性:每个jQuery对象,都有个context属性
作为参数:当使用jQuery选择器时,可以使用第二个参数context,细化了查询的范围
用Firebug试验一下就明白了!
4 data() / removeData()
在元素上(确切的说应该是jQuery对象)上存储数据的一种办法
5 queue() / dequeue()
用在jQuery动画效果上,可以方便的增加或者移除一个特效
6 delay()
暂停一段时间的动画效果
7 bind(), unbind(),live(), and die()
以前的文章说过了,不废话了
8 eq()
用数组下标的方式取得一组元素中的某一个
9 get()
取得jQuery元素对应的Dom对象格式
10 grep()
这个我挺喜欢,第二个参数是个用于过滤的回调函数,很容易懂的
var nums = '1,2,3,4,5,6,7,8,9,10'.split(',');
nums = $.grep(nums, function(num, index) {
// num = the current value for the item in the array
// index = the index of the item in the array
return num > 5; // returns a boolean
});
console.log(nums) // 6,7,8,9,10
11 Pseudo-Selectors
$(':animated'); // returns all elements currently animating
$(':contains(me)'); // returns all elements with the text 'me'
$(':empty'); // returns all elements with no child nodes or text
$(':parent'); // returns all elements with child nodes or text
$('li:even'); // returns all even-index elements (in this case, <li>s)
$('li:odd'); // can you guess?
$(':header'); // returns all h1 - h6s.
$('li:gt(4)'); // returns all elements with an (zero-based) index greater than the given number
$('li:lt(4)'); // returns all element with an index less than the given number
$(':only-child'); // returns all . . . well, it should be obvious
12 isArray() / isEmptyObject() / isFunction() / isPlainObject()
$.isArray([1, 2, 3]); // returns true
$.isEmptyObject({}); // returns true
$.isFunction(function () { /****/ }); // returns true
function Person(name) {
this.name = name
return this;
}
$.isPlainObject({})); // returns true
$.isPlainObject(new Object()); // returns true
$.isPlainObject(new Person()); // returns false
13 makeArray()
使用jQuery选择器返回的都是jQuery对象,所以$.makeArray()变得挺实用的
var ps = $('p');
$.isArray(ps); //returns false;
ps = $.makeArray(ps);
$.isArray(ps); // returns true;
14 map()
上面firebug的贴图中延伸过了,自己试试看吧
15 parseJSON()
把JSON格式的字符串结果解析成JSON对象
16 proxy()
$.proxy() 解决了函数调用的上下文问题
var person = {
name : "Andrew",
meet : function () {
alert('Hi! My name is ' + this.name);
}
};
person.meet(); // 正常工作
$('#test').click(person.meet); // 返回 Hi! My name is undefined 或者 Hi! My name is 空
$('#test').click($.proxy(person.meet, person));
// we could also do $.proxy(person, "meet")
17 replaceAll() / replaceWith()
用来替换内容的,replaceWith更顺脑
<div class="error1">error section 1</div>
<br/>
<div class="error2">error section 2</div>
<br/>
$('<span class=fixed>The error has been corrected</span>').replaceAll('.error1');
"$('.error2').replaceWith('<span class=fixed>The error has been corrected</span>');
18 serialize() / serializeArray()
看例子吧,易懂
<form>
<input type="text" name="name" value="John Doe" />
<input type="text" name="url" value="http://www.example.com" />
</form>
console.log($('form').serialize()); // logs : name=John+Doe&url=http%3A%2F%2Fwww.example.com
console.log($('form').serializeArray());
// logs : [{ name : 'name', value : 'John Doe'} , { name : 'url', value : 'http://www.example.com' } ]
19 siblings()
返回所有兄弟节点
20 wrap() / wrapAll() / wrapInner()
在作用对象的外面,周围,或者里面,包一层东西
Conclusion
好好玩这些个方法吧!
…
jQuery1.4发布: 你必须知道的15个新特性
一 18th
原文地址:jQuery 1.4 Released: The 15 New Features you Must Know
原文作者:James Padolsey
译文地址:jQuery1.4发布: 你必须知道的15个新特性
译文作者:Ji Hao
1. 传递属性给jQuery(…)构造器
早在1.4版本之前,jQuery就支持通过有用的”attr“方法为元素集合添加属性,参数可以传递属性的名-值对或者是一个指定了多个属性的对象。jQuery1.4则支持元素创建的时候传递一个属性对象作为jQuery构造器的第二个参数。
举例来说,如果你要用jQuery1.4创建一个有多个属性的超链接对象,用如下简单的代码即可实现:
jQuery('<a/>', {
id: 'foo',
href: 'http://google.com',
title: 'Become a Googler',
rel: 'external',
text: 'Go to Google!'
});
你可能已经注意到了”text”属性——可能你正怀疑它在这里出现是干啥的,毕竟超链接这玩意没有”text”属性!好吧,jQuery1.4其实统一了它自身的一些方法接受某些属性的行为。上面指定的”text”属性将会引起jQuery调用”.text()”方法,传递”Go to Google!”作为它的参数。
一个现实中更好点的例子:
jQuery('<div/>', {
id: 'foo',
css: {
fontWeight: 700,
color: 'green'
},
click: function(){
alert('Foo has been clicked!');
}
});
“id”被作为一个普通的属性添加,而”css”和”click”属性则触发了相应方法的调用。上面的代码在1.4之前需要链式的这样写出来:
jQuery('<div/>')
.attr('id', 'foo')
.css({
fontWeight: 700,
color: 'green'
})
.click(function(){
alert('Foo has been clicked!');
});
2. 所有的”until”方法!
在1.4中DOM遍历兵工厂里加入了3个新的方法, ”nextUntil“, “prevUntil“和 “parentsUntil“。这3个方法都是朝着某个方向遍历DOM直到指定的选择器条件满足。假定你有如下的水果列表:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Grape</li>
<li>Strawberry</li>
<li>Pear</li>
<li>Peach</li>
</ul>
如果你要选择”Apple”后面的直到”Strawberry”为止的所有列表元素,可以用如下简单的代码即可实现:
jQuery('ul li:contains(Apple)').nextUntil(':contains(Pear)');
// Selects Banana, Grape, Strawberry
更多请参考文档:prevUntil, nextUntil, parentsUntil
3. 绑定多个事件处理器
除了将多个事件绑定代码链式的写在一起之外,你还可以在一个bind方法里写多个事件绑定代码如下:
jQuery('#foo).bind({
click: function() {
// do something
},
mouseover: function() {
// do something
},
mouseout: function() {
// do something
}
})
这种写法对于.one()方法同样有效
更多请参考文档:.bind(…)
4. 按照每个属性的擦除(Easing)效果
以前你只能为单个动画指定其擦除效果,现在你能为当前定义动画效果的每个属性来指定擦除效果。jQuery包含了两个擦除效果”linear” 和”swing”(默认).其他的效果你需要单独下载。
要为每个属性指定擦除效果,只要把目标属性定义为数组即可,数组的第一个值是你要的动画效果设置的属性值,第二个值是擦除效果函数使用的值:
jQuery('#foo').animate({
left: 500,
top: [500, 'easeOutBounce']
}, 2000);
你还可以在可选参数options对象属性”specialEasing”里按照名-值对的形式定义每个属性的擦除效果:
jQuery('#foo').animate({
left: 500,
top: 500
}, {
duration: 2000,
specialEasing: {
top: 'easeOutBounce'
}
});
原文编辑注:本文的作者James Padolsey谦虚了,这个新特性其实是他的主意。
5. 全新的Live事件代理!
jQuery1.4增加了对”submit“, “change“, “focus” 和”blur“事件的代理支持。在jQuery中我们使用”.live()”方法来代理事件。当你需要对很多元素进行事件处理器注册的时候很有用,或者是当新的元素在将来被加入到DOM文档中我们却需要对其进行事件处理器绑定的情况下(使用”.live()”方法比进行重新绑定更高效)(译者注:更多关于jQuery事件代理请参考:Working with Events, Part 3: More Event Delegation with jQuery)
但是,要小心哪!你必须使用事件的名称,如果你要代理”focus”和”blur”,则必须用”focusin“和”focusout”
jQuery('input').live('focusin', function(){
// do something with this
});
6. 控制函数的上下文
jQuery1.4在其命名空间下提供了一个新的”proxy”函数。这个函数接受两个参数,一个”scope”加一个方法名,或者是一个函数加目标作用域。JavaScript的”this”关键字是非常难掌握的。有时候你希望它是你之前创建出来的对象而不是一个元素。
举个例子:我们有如下的一个”app”对象,它有两个属性,一个”clickHandler”方法和一个config对象:
var app = {
config: {
clickMessage: 'Hi!'
},
clickHandler: function() {
alert(this.config.clickMessage);
}
};
“clickHanlder”方法在被这样调用时”app.clickHandler()”将有”app”对象作为其上下文,也就是说”this”关键字访问的就是”app”。如果我们只是做这样的简单调用,这个工作起来完全没有问题:
app.clickHandler(); // "Hi!" is alerted
让我们来试试将其作为事件处理器来绑定到某个事件上:
jQuery('a').bind('click', app.clickHandler);
当我们点击超链接的时候,它看上去并没有工作(因为没有警告消息弹出来)。这是因为jQuery(以及大多数健全的事件模型)都默认的将事件处理器的上下文设置成了事件目标元素——即:使用”this”访问的其实是被点击的元素。但是我们并不想要这样的结果,我们希望”this”能够访问”app”对象。在jQuery1.4中实现这个再容易不过了:
jQuery('a').bind(
'click',
jQuery.proxy(app, 'clickHandler')
);
现在不管什么时候点击超链接,总是会有”Hi!”这个警告消息。
这个proxy函数返回你的函数的一个包装过的版本,”this”被设置成你指定的值。proxy函数在其他上下文也是有用的,例如传递一个回调函数给其他的jQuery方法或者传递给插件。
更多请参考文档:jQuery.proxy
7. 延迟一个动画队列
你现在可以为你的动画队列设置一个延迟。事实上任何队列都能设置延迟,但是最通用的场景应该是”fx”队列。它允许你在动画之间暂停,而不用再使用回调函数和”setTimeout”写的乱七八糟的。”.delay()”的第一个参数是你要延迟的毫秒数。
jQuery('#foo')
.slideDown() // Slide down
.delay(200) // Do nothing for 200 ms
.fadeIn(); // Fade in
如果你要延迟默认的”fx”队列之外的队列,则需要传递队列的名称作为第二个参数。
更多请参考文档:.delay(…)
8. 检查是否一个元素包含某些元素
jQuery1.4是的检查一个元素或者一个集合是否”.has()”某些元素更加容易。程序上等同于jQuery选择过滤器”:has()”。这个方法将选择当前集合内的符合参数(选择器)的所有元素。
jQuery('div').has('ul');
上面的这行代码将选择所有包含UL元素的所有DIV元素。这个情况下你用选择过滤器 (“:has()”)也够用了,但是这个方法在你需要用编程的方式过滤一个集合的时候是很有用的。
jQuery1.4 在jQuery名称空间下还提供了一个 “contains”函数。这是一个底层的函数,接受两个DOM节点作为参数,返回boolean值以指示第二个元素是否在第一个元素内。看下面的例子:
jQuery.contains(document.documentElement, document.body); // Returns true - <body> is within <html>
更多请参考文档:.has(…), jQuery.contains(…)
9. 解除元素的包装
有”.wrap()”方法已经一段时间了,jQuery1.4新增了”.unwrap()”方法做的是和”wrap()”完全相反的事情。假定有如下的DOM结构:
<div> <p>Foo</p> </div>
我们可以解除段落元素的包装:
jQuery('p').unwrap();
结果DOM结构如下:
<p>Foo</p>
本质上,这个方法简单的去除了任何元素的父元素
更多请参考文档:.unwrap(…)
10. 删除元素而不删除其数据
新的 ”.detach()“方法允许你从DOM文档中删除元素,和”.remove()”方法很像。关键的区别在于这个方法不会删除jQuery保存在这个元素上的数据。这些数据也包含使用”.data()”加上去的数据,也包含使用jQuery事件机制加上去的事件处理器。
这个适用于需要从DOM删除元素然后还要再加入DOM中的情况。被.detach的元素的事件监听器以及其他数据都会被保留。
var foo = jQuery('#foo');
// Bind an important event handler
foo.click(function(){
alert('Foo!');
});
foo.detach(); // Remove it from the DOM
// … do stuff
foo.appendTo('body'); // Add it back to the DOM
foo.click(); // alerts "Foo!"
更多请参考文档:.detach(…)
11. index(…)的增强
jQuery1.4提供了两种新的方法使用”.index()”方法。之前,你只能传递一个元素作为它的参数,改方法返回一个数字只是当前集合中目标元素的位置。
如果不传参数,则返回当前元素在同辈元素中的位置。假定我们有下面的DOM结构:
<ul> <li>Apple</li> <li>Banana</li> <li>Grape</li> <li>Strawberry</li> <li>Pear</li> <li>Peach</li> </ul>
当一个列表选项被点击的时候你想要知道他在其他列表选项中的位置:
jQuery('li').click(function(){
alert( jQuery(this).index() );
});
jQuery1.4还允许你指定一个选择器作为”.index()”方法的第一个参数,这么做将返回当前元素在选择器工作产生的结果集里的位置。
要注意的是这个方法返回整数值,如果选择器没有匹配的结果则返回-1
更多请参考文档:.index(…)
12. DOM操作方法接受回调函数作为参数
现在大多数的DOM操作方法都支持接受一个函数作为单个参数(或者第二个参数,如果是”.css()”和”.attr()”方法的话)。这个传递的函数将会为每个集合中的元素都运行一遍,函数的返回结果将作为DOM操作方法的值。
下面的方法都有接受回调函数作为参数的能力:
- after
- before
- append
- prepend
- addClass
- toggleClass
- removeClass
- wrap
- wrapAll
- wrapInner
- val
- text
- replaceWith
- css
- attr
- html
在这个回调函数里,你可以通过”this”访问当前正在遍历的元素,回调函数的第一个参数的值是当然遍历元素的位置。
jQuery('li').html(function(i){
return 'Index of this list item: ' + i;
});
还有,上面某些方法,在回调函数中还可以接收第二个参数。如果你正在调用一个设值方法(如”.html()”或者”.attr(‘href’)”)你可以访问当前要设置成的值,例如:
jQuery('a').attr('href', function(i, currentHref){
return currentHref + '?foo=bar';
});
正如你所看到的使用”.css()”和”.attr()”方法的时候,你可以传递函数作为第二个参数,因为第一个参数是你想要改变的属性的名称。
jQuery('li').css('color', function(i, currentCssColor){
return i % 2 ? 'red' : 'blue';
});
13. 判断对象的类型
jQuery1.4增加了两个副主函数(在jQuery名称空间下)帮助你检测正在处理的对象类型。
首先,有个”isEmptyObject”,这个函数返回boolean值,指示传递的对象是否为空(没有属性-直接或者间接的)。其次,有个”isPlainObject”,这个函数返回boolean值,指示传递的对象是否是一个纯的JavaScript对象,即使用”{}”或者”new Object()”创建出来的对象。
jQuery.isEmptyObject({}); // true
jQuery.isEmptyObject({foo:1}); // false
jQuery.isPlainObject({}); // true
jQuery.isPlainObject(window); // false
jQuery.isPlainObject(jQuery()); // false
更多请参考文档: isPlainObject(…), isEmptyObject(…)
14. closest()的增强
jQuery的”.closest()”方法现在能接受一组选择器作为参数。这个特性使得你在遍历一个元素祖先节点的时候,或者查找(多个)含有某些特定字符的最近元素的时候更有用。
除此之外,本方法还接受一个context作为其第二个参数,意思是你能控制遍历的深度。这两项增加适用的场景不是很多,但是jQuery内部使用这个方法来获得更好的性能。
更多请参考文档:.closest(…)
15. 新事件!focusIn 和 focusOut
其实上文已经提到,要代理”focus”和”blur”事件,你必须使用新的事件名称”focusin”和”focusout”。这些事件允许你在元素或者某元素的子元素获得焦点的时候干一些事情。
jQuery('form')
.focusin(function(){
jQuery(this).addClass('focused');
});
.focusout(function(){
jQuery(this).removeClass('focused');
});
你还应该注意到的一点是,这些事件是不传播的(冒泡),他们是捕获型事件。意思就是,最外层的元素首先触发该事件,然后才是”目标”元素。
享受最受期望的,最具特色的,到目前为止性能最好的jQuery1.4吧!
好吧,差不多了。我已经把自己认为对你们有影响的新特性涵盖到了。
如果你还没有准备好,应该看看”14 days of jQuery“,一个很酷的为jQuery1.4发布以及jQuery4岁生日准备的在线活动。
还有不要忘记看看新的API 文档!
–
Working with Events, Part 3: More Event Delegation with jQuery
一 17th
原文地址:http://www.learningjquery.com/2009/09/working-with-events-part-3-more-event-delegation-with-jquery
原文作者: Louis-Rémi Babé
正如本系列的第一篇文章中描述的那样,事件代理是利用事件冒泡机制来避免多次绑定事件监听器的一种办法。jQuery1.3和即将到来的jQuery1.4有很多新的特性可以使你的网页中使用事件代理更容易。这篇指南的目标就是帮助你理解这些新特性是如何工作的。
从传统的事件监听到事件代理
既然一个DOM元素上发生的事件会被传递到它所有的祖先元素(或者说是DOM节点)上,那么一个事件监听器就能被绑定在众多DOM元素的单一的那个祖先节点上,而不用为所有的DOM元素每个都单独绑定事件监听器。
看下面的列表先,再考虑下面的问题:
<ul class="myList"> <li class="red">The first item.</li> <li class="green">The second item.</li> <li class="yellow">The third item.</li> <li class="blue">The fourth item.</li> </ul> <p>Class of the last clicked item: <span id="display"> </span> </p>
如果我们想知道被点击的列表元素的class,使用传统事件监听器的jQuery代码应该是这样写的:
$("li").click( function( event ) {
$("#display").text(event.target.className);
});
传递给事件处理器的参数event对象有一个target属性,对应于被点击的元素。
使用事件代理的等价的代码是这样写的:
$("ul").click( function( event ) {
$("#display").text(event.target.className);
});
试试看实际效果:
- The first item.
- The second item.
- The third item.
- The fourth item.
Class of the last clicked item:?
事件代理有两个主要的优势:
1. 使用一个事件监听器代替多个事件监听器明显更快
2. 任何页面加载完成之后动态新插入的元素也将会拥有相同的行为(在Working with Events, Part 1中已经演示过了)
这个转换成事件代理太简单了,因为我们原来的目标只是显示列表元素的class。使用前面的这个代码片断,无序列表本身的class(myList,点列表那个黑点的左边就能看出效果)也会被显示出来。因此,我们还应该判断一下点击的目标是个<li>元素。
$("ul").click( function( event ) {
if(event.target.nodeName == "LI") {
$("#display").text(event.target.className);
}
});
试试看现在的效果:
- The first item.
- The second item.
- The third item.
- The fourth item.
Class of the last clicked item: ?
扫描event.target的祖先节点: .closest() 方法
操作像上面的例子一样如此简单的DOM文档,使用事件代理非常容易搞定。但是如果列表项里还包含子元素的话事情就会变得复杂许多,如下面这个列表元素:
<ul class="myList"> <li class="red"><b>The <i>first <u>item</u></i></b>.</li> <li class="green"><b>The <i>second <u>item</u></i></b>.</li> <li class="yellow"><b>The <i>third <u>item</u></i></b>.</li> <li class="blue"><b>The <i>fourth <u>item</u></i></b>.</li> </ul> <p>Class of the last clicked item: <span id="display"> </span> </p>
这种情况下,如果用户点击了 item 这个单词,event.target就会使<u>.这样的话就必须遍历当前目标元素的所有的祖先节点,来找到我们关心的元素:即<li>.
$("ul").click( function( event ) {
var elem = event.target;
while( elem.nodeName != "LI" && elem.parentNode) {
elem = elem.parentNode;
}
if(elem.nodeName == "LI") {
$("#display").text(event.target.className);
}
});
注意如果用户点击到<li>的外面,我们需要在某个时候停止对祖先节点的循环,这个例子,我们会一直找到根节点(根节点没有父节点)。
jQuery1.3引入了一个.closest() 方法,可以用一行代码替换刚刚的循环。
$("ul").click( function( event ) {
var $elem = $(event.target).closest("li");
if($elem.length) {
$("#display").text($elem.attr("class"));
}
});
试试看用.closest()的效果是不是还正确:
- The first item.
- The second item.
- The third item.
- The fourth item.
Class of the last clicked item:?
传递给.closest()方法的参数是一个CSS选择器,这个选择器将会匹配第一个感兴趣的祖先节点。
上下文参数
可以这样说:当点击事件发生在<li>外面的时候,我们可以在查找的祖先节点在找到<ul>的时候就停止,而不用等到一直文档根节点才停止循环。jQuery1.4将会引入一个可选的context参数到.closest()方法来达到这个目的。
$("ul").click( function( event ) {
$("#display").text($(event.target).closest("li", this).attr("class"));
});
这里的this即事件监听器绑定的<ul>元素。这个可选参数因为避免了查找可能不存在的祖先节点的资源浪费,从而提高了事件代理的性能。
用一行代码实现事件代理: .live()方法
jQuery1.3引入了一个.live()方法,这个方法绑定事件监听器的时候隐式调用.closest()方法来决定事件监听器是不是该被执行。
$("li").live("click", function( event ) {
$("#display").text(
$(event.currentTarget).attr("class")
);
});
注意使用.live()方法的语法是不同的。看上去我们换回了传统的事件绑定的写法。但是最大的不同是,这样.live()方法写的事件监听器对于当前页面中已存在的元素和之后动态插入的元素都是有效的。当然没什么神秘的:.live()方法幕后只是把事件监听器绑定在文档根节点上,然后使用.closest()方法过滤任何event.target.
和传统的事件绑定语法相比一个值得注意的区别是,在事件处理器内部,我们不再使用event的target属性,而是使用currentTarget。事实上,event对象的target可能是一个<li>的子元素,而currentTarget属性则是被隐式的.closest()方法找到的元素。
正如在Event对象文档中将的,currentTarget属性应该是事件冒泡阶段的当前DOM元素,即:事件监听器检测到的元素总是事件监听器被绑定的元素。当使用.live()方法的时候,currentTarget总是文档根节点,你需要再一次用.closest()方法根据target找到感兴趣的祖先节点。
$("li").live("click", function( event ) {
$("#display").text(
$(event.target).closest("li").attr("class")
);
});
如果使用jQuery1.3则必须要写成这样,如果使用jQuery1.4,currentTarget已经在内部被默认修改掉了,可以避免在事件处理器内部使用额外的.closest()方法来查找目标。
上下文参数
在jQuery1.3中所有使用live方式的事件监听器实质上都是绑定在DOM文档根节点上的。因为一个事件监听器检测到的所有事件都将触发执行隐式的.closest()方法,即使事件的目标元素不是我们所感兴趣的,所以这将影响网页的性能。
在jQuery1.4中.live()方法利用jQuery对象的上下文参数,它能够将事件监听器绑定到文档的一个具体的我们关心的元素上:
$("li", $("ul")[0]).live("click", function( event ) {
$("#display").text(
$(event.currentTarget).attr("class")
);
});
上下文参数就是创建jQuery对象的第二个参数。为了对.live()方法有用,它必须被置成一个纯的DOM元素,这就是为什么$(“ul”)后面跟了个[0]的原因。Brandon Aaron 有一篇有用的文章详细解释了上下文参数 。
解除.live()绑定: .die()方法
就像.bind()和.unbind()互为补充允许事件的绑定和解除绑定,.live()也有与其互为补充的.die()方法。
和.bind()不一样的是.live()不支持使用 namespaced events。
处理不冒泡的事件
事件代理对于有些事件不能实现,因为这些事件不会冒泡。jQuery1.4允诺.live()方法依然能够支持这些不冒泡的事件。这个已经实现,而且将会在接下来的第四篇文章中被涵盖到。
本文包含的脚本:
—
Working with Events, part 2
一 12th
原文地址:http://www.learningjquery.com/2008/05/working-with-events-part-2
原文作者: Karl Swedberg
在我的上一篇文章中,描述了一个常见的问题,即事件对新加入HTML文档的元素表面上不工作的情况,不管这个元素是通过ajax方式还是修改DOM的方式加入进来的。我们也检查了一个解决此问题办法:事件代理。使用这种办法,我们将事件绑定到一直在DOM中的容器元素上然后再检查事件发生的目标元素。
Cloning Nodes
这一次,我们将一起看看解决此问题的另一个方法:重新绑定事件处理器。但是这么做之前,我应该要提一下,在jQuery1.2中事件处理器能够随着元素一起被克隆。看这个无序列表:
<ul id="list3" class="eventlist"> <li>plain</li> <li class="special">special <button>I am special</button></li> <li>plain</li> </ul>
我们可以拷贝一个<li class=”special”>然后插入到被拷贝的元素后面,同时取得任何绑定在原来元素上的事件处理器。jQuery提供的这个.clone()方法不会为我们把这任务都干了,它只会做元素的拷贝
$(document).ready(function() {
$('#list3 li.special button').click(function() {
var $parent = $(this).parent();
$parent.clone().insertAfter($parent);
});
});
试试看:
- plain
- special
- plain
正如你所看到的,原按钮能够继续创建新的列表元素,但是“动态生成”的列表元素内的按钮不能创建新的按钮。
为了使得事件处理器也能被拷贝到新的元素上,我们只需要传递true给clone方法:
$(document).ready(function() {
$('#list4 li.special button').click(function() {
var $parent = $(this).parent();
$parent.clone(true).append(' I\'m a clone!').insertAfter($parent);
});
});
注:我加了个.append(‘ I\’m a clone!’)只是为了让发生的事情看上去更明显。
试试看:
- plain
- special
- plain
当我们想拷贝已有元素及其事件处理器的时候使用.clone(true)尤为有效,但是还有很多其他和克隆不相关的情况我们也希望事件处理器能够被保留。
Re-binding基础
re-binding的概念相当直接:我们定义一个绑定事件处理器的函数,然后每当有新元素加入的时候调用这个函数。例如:上面的无序列表,我们首先创建一个addItem函数,这个函数注册一个事件处理器,这个事件处理器的意图是点击事件发生的时候,添加一个新的列表元素。
function addItem() {
$('#list5 li.special button').click(function() {
var $newLi = $('<li>special and new <button>I am new</button></li>');
$(this).parent().after($newLi);
});
下一步,当DOM加载完成的时候调用这个函数:
$(document).ready(function() {
addItem();
});
最后我们在click事件处理器内再次调用这个函数,这样做的话,新加入的元素也能绑定事件处理器。
我们在多加一个事件处理器绑定在按钮上,但是不为这个做re-bind,为了试验的时候能看出区别。
为#list5内button做处理的全部的代码:
function addItem() {
$('#list5 li.special button').click(function() {
var $newLi = $('<li>special and new <button>I am new</button></li>');
$(this).parent().after($newLi);
addItem();
});
}
$(document).ready(function() {
addItem();
// non-rebinding click handler ...
$('#list5 li.special button').click(function() {
$(this).after(' pressed');
});
});
试试看(IE下还是不要点击了,死循环啊!!!):
- plain
- special
- plain
可以看到每当第一个列表项的按钮被点击的时候”pressed”会被添加到这个列表项的后面,但是不会被添加到我们动态创建的列表元素的后面。另一方面,动态创建出来的按钮也能创建新的列表元素,因为函数已经被重新绑定过了。
然而,如果我们点击不只一次这个按钮,就会发现我们刚刚做的这一切产生了不受欢迎的结果。每点击一个按钮都会再绑定一次事件处理器,产生乘法的效果,即:第1次点击产生1个额外的列表项,第2次点击产生2个,第2次点击产生4个,循环下去。
Unbind和Bind
为了避免乘积型的绑定,我们可以先解除绑定然后再重新绑定。所以上面代码的第二行,我们将替换原来的
$(‘#list5 li.special button’).click(function() {
为
$(‘#list6 li.special button’).unbind(‘click’).bind(‘click’,(function() {
注意这里的.bind()方法,这是jQuery通用的事件绑定处理方法。所有其他的诸如.click(), .blur(), .resize()等等都是等价的.bind(‘event’)的简写形式。
全部的代码如下,作为对比再看一下非重新绑定的事件处理器代码
function addItemUnbind() {
$('#list6 li.special button')
.unbind('click')
.bind('click', function() {
var $newLi = $('<li>special and new <button>I am new</button></li>');
$(this).parent().after($newLi);
addItemUnbind();
});
}
$(document).ready(function() {
addItemUnbind();
// non-rebinding click handler
$('#list6 li.special button').click(function() {
$(this).after(' pressed');
});
});
看看这次它怎么工作?
- plain
- special
- plain
不幸的是,我们尝试解除函数addItemUnbind()绑定的方法过头了,把”non-rebinding”的点击处理器(甚至它连一次运行的机会都没得到)也解除了绑定,(证据可以从运行结果看出来,因为在”I am special”的按钮后面没有加上”pressed”的文本)。很明显,我们将不得不对我们需要解除绑定的东西更加小心。
使用事件名称空间
一种避免过度的解除绑定的方法是为绑定和解除绑定的相应点击事件加上“名称空间”。所以,不同于.bind('click') 和 .unbind('click)例如我们用这样的方法.bind('click.addit') 和 .unbind('click.addit').这是一个代码的示例除了使用有名称空间的事件之外和之前的代码基本一样。
function addItemNS() {
$('#list7 li.special button')
.unbind('click.addit')
.bind('click.addit', function() {
var $newLi = $('<li>special and new <button>I am new</button></li>');
$(this).parent().after($newLi);
addItemNS();
});
}
$(document).ready(function() {
addItemNS();
// non-rebinding click handler
$('#list7 li.special button').click(function() {
$(this).after(' pressed');
});
});
终于,我们有了期望得到的这一堆按钮和其被加上的正确的事件行为。(IE下还是不要点击了,这个也会产生死循环啊!!!):
- plain
- special
- plain
请阅读Brandon Aaron的文章以了解更多关于事件名称空间的知识: Namespace Your Events.
Bonus:通过函数引用的方式解除绑定
如果你一直看到这里,证明你是个非常有耐心的人,所以我将特别奖励一个重新绑定的终极方法。除了使用事件名称空间之外,我们还可以在调用.bind()和.unbind()的方法时,增加第二个参数以引用函数。我们需要稍微调整一下代码防止递归,最终下面的代码应该是OK的.
function addItemFinal() {
var $newLi = $('<li>special and new <button>I am new</button></li>');
$(this).parent().after($newLi);
$('#list8 li.special button')
.unbind('click', addItemFinal)
.bind('click', addItemFinal);
}
$(document).ready(function() {
$('#list8 li.special button').bind('click', addItemFinal);
// non-rebinding click handler
$('#list8 li.special button').click(function() {
$(this).after(' pressed');
});
});
注意这里在bind和unbind里的addItemFinal是没有括号的,因为我们只是在引用函数,而不是在做函数调用,让我们最后再测试一下吧:
- plain
- special
- plain
实现此功能可选的jQuery插件
有三个很棒的插件能为我们干上面的事:
- Live Query by Brandon Aaron
- Listen by Ariel Flesler
- Intercept by Ariel Flesler
如果本文让你困惑的或者你只想要一个快速的测试过的解决方案,你一定要试试这几个插件中的一个,每个插件工作起来略有不同,但是都用样精彩。
更新:使用事件名称空间的添加删除例子
回复Nick Johns 下面的评论,我做了一个允许增加和删除的例子,代码基于我们所讲的”使用事件名称空间”的方法如下:
function addRemoveItemNS() {
var $newLi = $('<li>special and new <button>I am new</button> <button>remove me</button></li>');
$('#list9 li.special')
.find('button.addone')
.unbind('click.addit')
.bind('click.addit', function() {
$(this).parent().after($newLi);
addRemoveItemNS();
})
.end()
.find('button.removeme')
.unbind('click.removeit')
.bind('click.removeit', function() {
$(this).parent().remove();
});
}
$(document).ready(function() {
addRemoveItemNS();
});
我为初始的按钮家了一个”addone”的class,否则列表就和其他一样了,试试下面的例子:
- plain
- special
- plain
<ul class="eventlist" id="list9"> <li>plain</li> <li class="special">special <button class="addone">I am special</button></li> <li>plain</li> </ul>
本文所包含的脚本:
Working with Events, part 1
一 7th
原文地址:http://www.learningjquery.com/2008/03/working-with-events-part-1
原文作者: Karl Swedberg
CSS和JavaScript有很多的不同,其中大多数区别都很明显不用说出来。然而,他俩的一处区别值得一 提,因为这个区别常常引起困惑和吃惊,尤其是对那些从CSS专家转职为jQuery新手的人。事实上,这是早在2006年我向jQuery邮件列表提出的 第一个问题。从那之后,我至少每周能看到类似的问题,有时候甚至每天都有,尽管jQuery已经提供了FAQ page and 这 三个 插件在解决这个问题。
CSS和JavaScript如何不同?
举个例子,假如我们html文档中有”<button>Alert!</button>“,我们想要为它加上点击事件处理,让它在被点击的时候产生一个alert消息。在jQuery中用如下的代码实现:
$(document).ready(function() {
$('button.alert').click(function() {
alert('this is an alert message');
});
});
这里我们在页面加载完成之后为定义了class等于”alert”的button注册一个点击事件。按钮已经在这了,我们为其绑定了一个点击事件。如果我们之后再动态插入第二个按钮<button>,然而这个时候第二个按钮是完全不知道点击事件处理器的。点击事件在第二个按钮存在之前已经处理完了。因此第二个按钮不会产生alert消息。
对新加的Elements事件处理器不起作用
$('#create-button').click(function() {
if ( $('button.alert').length <2) {
$('<button class="alert">Not another alert').insertAfter(this);
}
return false;
});
对新加的Element CSS依然是工作的
<ul id="list1" class="eventlist"> <li>plain</li> <li class="special">special <button>I am special</button></li> <li>plain</li> </ul>
- plain
- special
- plain
$(document).ready(function() {
$('#list1 li.special button').click(function() {
var $newLi = $('<li class="special">special and new <button>I am new</button></li>');
$(this).parent().after($newLi);
});
});
事件委派: 让事件拥抱新的Elements
$(document).ready(function() {
$('#list2').click(function(event) {
var $newLi = $('<li class="special">special and new <button>I am new</button></li>');
});
$(document).ready(function() {
$('#list2').click(function(event) {
var $newLi = $('<li class="special">special and new <button>I am new</button></li>');
var $tgt = $(event.target);
if ($tgt.is('button')) {
$tgt.parent().after($newLi);
}
// next 2 lines show that you've clicked on the ul
var bgc = $(this).css('backgroundColor');
$(this).css({backgroundColor: bgc == '#ffcccc' || bgc == 'rgb(255, 204, 204)' ? '#ccccff' : '#ffcccc'});
});
});
- plain
- special
- plain
var list2 = document.getElementById('list2');
list2.onclick = function(e) {
var e = e || window.event;
var tgt = e.target || e.srcElement;
if (tgt.nodeName.toLowerCase() == 'button') {
// do something
}
};
正如你看到的,代码有点纠缠。
使用事件代理的另一个巨大的好处
$(document).ready(function() {
$('table').click(function(event) {
var $thisCell, $tgt = $(event.target);
if ($tgt.is('td')) {
$thisCell = $tgt;
} else if ($tgt.parents('td').length) {
$thisCell = $tgt.parents('td:first');
}
// now do something with $thisCell
});
});
注意上面的代码的else块中我考虑了点击单元格内子元素的情况,但这只是事件代理带来巨大性能提升的同时伴随的一个小小的不方便。
下期带来
在本教程的第二部分的,我们将会通过小心放置函数调用位置的方法来将事件传递到新创建的元素上。当然也会检查非绑定的事件和使用命名空间的事件。同时,我希望大家觉得这一部分的教程是有用的。如果我在文章中有任何错误,特别是用辞方面的,请不要迟疑马上指出来。

