[翻译]改善你的jquery—25条jquery实用技巧<二>

2009-4-12

上一篇: 改善你的jquery—25条jquery实用技巧<一>

11.适当地使用动画效果

我第一次使用jQuery的时候就喜欢上了像slideDown()、fadeIn()等这些预定义的动画函数,使用它们可以很简单地做出很酷的动画效果。jQuery的animate()函数的强大和易用让人很容易进一步实现更好的效果,事实上,如果你看了jquery的源代码你会发现fadeIn()、slideDown()等这些函数的内部都使用了animate()函数,它们只是让animated()更易使用。

slideDown: function(speed,callback){
return this.animate({height: &quot;show&quot;}, speed, callback);
},

fadeIn: function(speed, callback){
return this.animate({opacity: &quot;show&quot;}, speed, callback);
}

animate()函数只是简单地接收所有的CSS属性,平滑地把属性从一个值转换到另一个值,形成动画。你可以使用它平滑地改变任何你想改变的属性,如width, height, opacity, background-color, top, left, margin, color, font-size等等。

下面这段简单的代码实现了当鼠标放在菜单上时菜单上所有列表元素的高度都平滑地改变到100px。

$('#myList li').mouseover(function() {
$(this).animate({&quot;height&quot;: 100}, &quot;slow&quot;);
});

animation函数不像jquery的其他函数,它是自动队列的,即如果你想在一个效果执行完后接着执行另一个效果,只需要连续使用两次animate函数,无需任何回调。

$('#myBox').mouseover(function() {
$(this).animate({ &quot;width&quot;: 200 }, &quot;slow&quot;);
$(this).animate({&quot;height&quot;: 200}, &quot;slow&quot;);
});

如果你想让两个动画同时执行,把参数放在一个object里,调用一次即可:

$('#myBox').mouseover(function() {
$(this).animate({ &quot;width&quot;: 200, &quot;height&quot;: 200 }, &quot;slow&quot;);
});

你可以传入值是数字的属性形成动画,如果要传入非数字的属性,那就要使用插件,例如平滑过渡颜色效果的插件:Color Animations

12.学习事件委托

使用jQuery可以很容易地为DOM元素绑定事件,但如果绑定太多事件会让程序效率降低,事件委托可以让你可以让你绑定更少的事件但达到同样的效果,解释事件委托最好的办法是通过例子:

$('#myTable TD').click(function(){
$(this).css('background', 'red');
});

这是一个简单的函数,为表格的所有单元格绑定事件,当鼠标点击单元格即变红色,假设表格有50行10列,那么总共绑定了500个事件。如果我们能值为table绑定一个事件,让事件处理函数找出所点击的单元格,再让它变成红色,那是再好不过的了。事实上,这就是事件委托,也是我们接下来要做的:

$('#myTable').click(function(e) {
var clicked = $(e.target);
clicked.css('background', 'red');
});

参数”e”包含了所有关于event信息,包括了实际接收鼠标点击的元素,我们所需要做的就是检查鼠标点击的是哪个单元格,非常简洁。

事件委派还有一个好处。当你为一个块(表格、列表或div块等)里所有的元素绑定事件,当增加元素到这个块里,新增加的元素并不会自动绑定事件,如果使用事件委托,事件绑定后即使新增加元素也可以正常工作。

13.用class保存状态

这是html块保存状态最基本的方法,jQuery擅长通过class操纵元素,因此如果你想储存状态信息,为什么不创建一个额外的的class去保存它呢?

这是一个例子,我们想创建一个可展开的菜单,点击按钮时如果面板是关闭的,则调用slideDown(),如果是打开着则调用slideUp(),先看看HTML:

&lt;div class=&quot;menuItem expanded&quot;&gt;
   &lt;div class=&quot;button&quot;&gt;
        click me
    &lt;/div&gt;
    &lt;div class=&quot;panel&quot;&gt;
        &lt;ul&gt;
            &lt;li&gt;Menu item 1&lt;/li&gt;
            &lt;li&gt;Menu item 2&lt;/li&gt;
            &lt;li&gt;Menu item 3&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/div&gt;

很简单,我们添加一个额外的class属性,目的只是为了说明元素现在的状态。添加后,我们要做的只是添加鼠标点击时执行slideUp()和slideDown()的事件处理函数。

$('.button').click(function() {

var menuItem = $(this).parent();
var panel = menuItem.find('.panel');

if (menuItem.hasClass(&quot;expanded&quot;)) {
menuItem.removeClass('expanded').addClass('collapsed');
panel.slideUp();
}
else if (menuItem.hasClass(&quot;collapsed&quot;)) {
menuItem.removeClass('collapsed').addClass('expanded');
panel.slideDown();
}
});

这是个很简单的例子,只作演示用,通过添加额外的class,你可以储存各种各样的值在HTML元素里。

然而,大多数情况下,使用下一条技巧里的方法更好。

14.使用jQuery的内部函数data()储存状态

jQuery有个内部函数data()可以用来在任何DOM元素上储存键/值形式的数据,因为一些原因,这个函数并没有很好的文档说明。储存数据就像下面写的这样简单:

$('#myDiv').data('currentState', 'off');

我们可以改良上一个例子的程序,我们仍然使用同样的HTML(但去掉class”expanded”),使用data()储存状态:

$('.button').click(function() {

var menuItem = $(this).parent();
var panel = menuItem.find('.panel');

if (menuItem.data('collapsed')) {
menuItem.data('collapsed', false);
panel.slideDown();
}
else {
menuItem.data('collapsed', true);
panel.slideUp();
}
});

我想你会同意,这样写比之前更简洁。要了解更多关于data()与removeData(),看这里:jQuery internals

15.创建自定义选择器

jQuery有很多内置的选择器可以通过id、class、标签、属性等查找元素,但如果你想通过其他jQuery里没有的方式查找元素,该怎么做?

或许可以在选择之前为元素添加一个class属性再进行选择,但其实扩展jQuery写新的选择器并不难。下面我们通过例子来说明:

$.extend($.expr[':'], {
over100pixels: function(a) {
return $(a).height() &amp;gt; 100;
}
});

$('.box:over100pixels').click(function() {
alert('The element you clicked is over 100 pixels high');
});

第一部分代码创建了一个新的选择器,用来查找高度大于100像素的元素。第二部分代码使用这个新选择器为所有符合条件的元素添加click事件。

关于自定义选择器在这里就不多说了,你可以上google搜索“custom jquery selector”,肯定能找到很多很好的例子。

16.合理化你的HTML,并在页面载入的时候修改它

这个标题看起来似乎没什么意义,但实际上这个技巧不仅可以让你的代码变得整洁,还可以减少页面的大小,对SEO也有帮助。看看下面的HTML:

&lt;div class=&quot;fieldOuter&quot;&gt;
    &lt;div class=&quot;inner&quot;&gt;
        &lt;div class=&quot;field&quot;&gt;This is field number 1&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;errorBar&quot;&gt;
        &lt;div class=&quot;icon&quot;&gt;&lt;img src=&quot;icon.png&quot; alt=&quot;icon&quot; /&gt;&lt;/div&gt;
        &lt;div class=&quot;message&quot;&gt;&lt;span&gt;This is an error message&lt;/span&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;fieldOuter&quot;&gt;
    &lt;div class=&quot;inner&quot;&gt;
        &lt;div class=&quot;field&quot;&gt;This is field number 2&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;errorBar&quot;&gt;
        &lt;div class=&quot;icon&quot;&gt;&lt;img src=&quot;icon.png&quot; alt=&quot;icon&quot; /&gt;&lt;/div&gt;
        &lt;div class=&quot;message&quot;&gt;&lt;span&gt;This is an error message&lt;/span&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

上面是一个表可能的结构,为了作为例子稍微做了下修改,我想你一定会觉得上面这段代码十分难看,如果表里有很长的内容,页面将会很长,重复元素也很多。如果只是放下面这段代码到你的页面,会更好:

&lt;div class=&quot;field&quot;&gt;This is field 1&lt;/div&gt;
&lt;div class=&quot;field&quot;&gt;This is field 2&lt;/div&gt;
&lt;div class=&quot;field&quot;&gt;This is field 3&lt;/div&gt;
&lt;div class=&quot;field&quot;&gt;This is field 4&lt;/div&gt;
&lt;div class=&quot;field&quot;&gt;This is field 5&lt;/div&gt;

我们需要做的只是使用jQuery做一点点处理,把之前那些需要重复的的HTML代码加进来,像这样:

$(document).ready(function() {
    $('.field').before('&lt;div class=&quot;fieldOuter&quot;&gt;&lt;div class=&quot;inner&quot;&gt;');
    $('.field').after('&lt;/div&gt;&lt;div class=&quot;errorBar&quot;&gt;&lt;div class=&quot;icon&quot;&gt;
        &lt;img src=&quot;icon.png&quot; alt=&quot;icon&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;message&quot;&gt;
        &lt;span&gt;This is an error message&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;');
});

不建议经常使用这个技巧,使用了它,在页面载入时会有闪烁的现象,但在有很多重复的HTML元素的情况下,这个技巧能有效地减小你页面的大小,对SEO也有好处,因为除去了很多重复无关的元素。

译者注:如果要考虑向后兼容,即考虑没有javascript的浏览器,任何情况下都不应该这样使用。

17.通过延迟加载内容提高速度和SEO友好度

还有另一个方法,可以加快页面载入,使爬虫蜘蛛抓取的页面更整洁,就是在页面其他部分载入完成后,再用AJAX载入内容。用户能看到正常的一面,爬虫蜘蛛也能只抓取到你想让它抓取的内容。

我们已经在自己的网站上使用这个技巧了,上面那些紫色的按钮能打开3个表单,一个导航和一个google map,这些都会让页面大小加倍,所以,我们把上面那些全部放在一个静态的HTML文件里,当页面读取完毕时再使用load()读取这个文件获得这部分元素,像这样:

$('#forms').load('content/headerForms.html', function() {
// 内容读取完毕时执行这里的代码,只执行一次
// 把所有事件处理程序都放这里
});

我不会到处使用这个技巧,你应该考虑它的优缺点,它会增加对服务器的请求,你的页面刚打开时载入的部分不能马上使用,但如果能正确地使用,它会是一个很好的优化技巧。

18.使用jQuery里的工具函数

jQuery里有很多实用的函数,填补了javascript的空白。

函数API见这里

特别地,浏览器对javascript里一些数组函数的支持并不好(IE7甚至不支持indexOf()),jQuery有迭代、筛选、复制、合并和去除重复元素这一系列针对数组的函数。

其他在javascript很难实现的功能,像获取下拉列表的值,在传统javascript里,必须使用getElementById获取<select>元素,再获取它所有的子元素,迭代检查它们有没有selected,十分繁琐。而使用jQuery很容易就能获取:

$('#selectList').val();

很值得花一点时间仔细看看jQuery文档,探索那些相对少人知道的函数。

19.同时使用多个框架时,用noconflict重命名jQuery对象

大部分javascript框架使用符号$作为记号,当页面上使用了超过一个框架时,这会产生冲突。幸运的是有一个很简单的解决方法,nofonflict()函数让你能自定义jQuery的名字:

var $j = jQuery.noConflict();
$j('#myDiv').hide();

20.怎样提示图片已经加载完毕

这个问题似乎没有怎么被提及到,但这在做相册的时候是很常见的问题,其实这个问题很简单。

你需要做的只是在<img>标签上使用.load()函数,给它一个回调函数。下面的例子改变了<img>标签的”src”属性,载入一张新的图片,并为它加了一个简单的load()函数。

$('#myImage').attr('src', 'image.jpg').load(function() {
alert('Image Loaded');
});

你会发现图片载入完毕时提示框会弹出。

21.总是使用最新版本

jQuery一直在改进,它的创建者John Resig一直在寻找方法改进jQuery性能。

jQuery现在的版本是1.2.6(翻译时已经是1.3.2),但john透露它在开发一个新选择器引擎:Sizzle 。它能提升选择器的效率,在firefox里能达到4倍。所以,应该使用最新版本以获得更好的性能。

译者注:sizzle引擎已经开发完成,jquery1.3已经使用此引擎,sizzle主页:http://sizzlejs.com/

22.怎样检查元素存在

在你操纵一个元素前你不需要检查那个元素是否存在,因为如果你选择的元素不在DOM里jQuery不会做任何事。但如果你需要检查是否有元素被选择了,或者检查有多少个元素被选择,你可以使用length属性。

if ($('#myDiv).length) {
// 你的代码
}

很简单,但并不易见。

23.用js向HTML标签添加一个class属性

我是从Karl Swedberg的两本书 (1) (2) 里学到这招。

他在我最近的一片文章的评论里提到这个技巧,它的原理是这样的:

首先,jQuery加载完成后用它为<HTML>标签增加一个名为”JS”的class属性:

$('HTML').addClass('JS');

因为这只会在javascript可用的情况下发生,所以你可以利用它添加只有javascript可用时才有的css属性,像这样:

.JS #myDiv{display:none;}

这意味着,当javascript可用时我们可以隐藏一些内容,再在需要时用jQuery让它显现,而javascript不可用时(以及搜索引擎抓取页面时),内容并没有隐藏,用户能正常看到那些内容。我会在以后经常使用这个技巧。

可以来这里读取Karl Swedberg关于这个例子的全文:

24.返回”false”阻止默认行为

这可能是显而易见的,但有时候却不是,如果你习惯这样做:

&lt;a href=&quot;#&quot; class=&quot;popup&quot;&gt;Click me!&lt;/a&gt;

然后给它绑定一个事件,像这样:

$('popup').click(function(){
// Launch popup code
});

它会很好的工作,直到你在一个长页面使用它,才会发现问题,你会发现”#”使鼠标点击它时自动返回页面顶部。

你需要做的是阻止它的默认行为,在事件处理函数里添加”return false”可以阻止任何事件的任何默认行为:

$('popup').click(function(){
// Launch popup code
return false;
});

25.缩写ready事件

这是个很小的技巧,可以通过缩写函数$(document).ready为你腾出几个字节的空间。

可以把

$(document).ready(function (){
// your code
});

缩写成这样:

$(function (){
// your code
});

后话

终于翻译完了,好长的文章,真佩服他这么有耐性写这么长的文章。似乎我耐心还是不够,一口气是翻译不了那么长的,分了好几个次。第二部分代码还没排版,没有缩进,以后再修改。

评论

[…] 继续阅读:改善你的jquery—25条jquery实用技巧<二> […]

2009年4月12日 21:51

Good!王子,加油!

[…] 继续阅读:改善你的jquery—25条jquery实用技 巧<二> […]