jQuery 最佳实践
2014-03-19 · 1,794 chars · 9 min read
本文介绍一些使用 jQuery 的通用标准和最佳实践,这些标准不涵盖 Javascript 的标准和最佳实践,英文原文地址是 http://lab.abhinayrathore.com/jquery-standards/。
加载 jQuery#
1、尽量使用 CDN 加载:
<script type="text/javascript" src="ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>" <script>window.jQuery || document.write('<script src="js/jquery-1.11.0.min.js" type="text/javascript"><\/script>')</script>
2、就像上面的代码一样,在 CDN 加载失败时,要回源到本地服务器的同版本 jQuery。
3、使用依赖协议的 URL(不加http:
和https:
,直接使用//
),参看上面的例子。
4、尽可能在页面底部加载 jQuery 和 javascript。
5、如何选择 jQuery 版本?
- 如果要兼容 IE6/7/8,不要使用 2.x 版本的
- 对于新的应用,如果不考虑一些插件的兼容性问题,尽可能的使用最新版
- 从 CDN 加载 jQuery 的时候,使用完整的版 本号(例如,使用 1.11.0,不用 1.11 和 1)
- 不要加载多个版本的 jQuery
6、如果你使用了 Prototype, MooTools, Zepto 等,尝试使用jQuery
代替$
。可以使用$.noConflict()
让出$
的控制权。
jQuery 变量#
1、所有被缓存的 jQuery 对象,变量名以$
开头。
2、总是缓存 jQuery 选择器返回的对象,方便复用:
var $myDiv = $("#myDiv"); $myDiv.click(function(){...});
3、使用驼峰命名。
选择器#
1、尽可能的使用 ID 选择器。ID 选择器使用document.getElementById()
,所以更快。
2、当使用类选择器的时候,不要加 DOM 元素类型:
var $products = $('div.products') // 慢 var $products = $('.products') // 快
3、使用 find 查找 ID->Child 的嵌套查询,.find()
方法更快,因为第一次选择没有使用 jQuery 的选择器引擎:
// 差, 全部使用jQuery的选择器引擎 var $productIds = $('#products div.id') // 好, #products使用document.getElementById(), 只有div.id需要使用jQuery的选择器引擎 var $productIds = $('#products').find('div.id')
4、越靠右侧越具体:
// 差 $('div.data .gonzalez') // 最佳 $('.data td.gonzalez')
5、选择器不要太“具体”:
$('.data table.attendees td.gonzalez') // 更好,尽可能省去中间部分 $('.data td.gonzalez')
6、给 选择器指定上下文(限定范围):
// 慢,因为它在整个DOM结构中查找 $('.class') // 快,因为它只查找 class-container 下的. $('.class', '#class-container')
7、避免使用“*”:
$('div.container > *') // 差 $('div.container').children() // 好
8、避免隐式使用“*”:
$('div.someclass :radio') // 差,还是用了“*” $('div.someclass input:radio') // 好
9、不要使用多个 ID 选择器,或者嵌套使用 ID 选择器,单独的 ID 选择器使用document.getElementById()
,速度很快:
$('#outer #inner') // 差 $('div#inner') // 差 $('.outer-container #inner') // 差 $('#inner') // 好, 调用 document.getElementById()
DOM 操作#
1、先把元素分离出 DOM 结构,再进行复杂的操作,之后再附加回 DOM 中。不明白原因的话,可以了解下.detach()
这个方法
var $myList = $('#list-container > ul').detach() // 对 $myList 执行大量复杂操作 $myList.appendTo('#list-container')
2、使用字符串连接或者 array.join(),少用.append(),点击这里查看性能比较。
// 慢 var $myList = $('#list') for (var i = 0; i < 10000; i++) { $myList.append('<li>' + i + '</li>') } // 快 var $myList = $('#list') var list = '' for (var i = 0; i < 10000; i++) { list += '<li>' + i + '</li>' } $myList.html(list) // 更快 var array = [] for (var i = 0; i < 10000; i++) { array[i] = '<li>' + i + '</li>' } $myList.html(array.join(''))
3、不要对不存在的元素做操作:
// 差: 在发现该ID不存在之前,已经执行了3个函数 $('#nosuchthing').slideUp() // 好 var $mySelection = $('#nosuchthing') if ($mySelection.length) { $mySelection.slideUp() }
事件#
1、一个页面只使用一个 Document ready,便于调试和跟踪。
2、不要使用匿名函数绑定事件,匿名函数不利于调试,复用,测试,debug:
$("#myLink").on("click", function(){...}); // 差 // 好 function myLinkClickHandler(){...} $("#myLink").on("click", myLinkClickHandler);
3、Document ready 不要用匿名函数,原因同上:
$(function(){ ... }); // 差: 你没办法写单元测试和复用 // 好 $(initPage); // or $(document).ready(initPage); function initPage(){ //... }
4、Document ready 的处理函数应该写在外部文件,内联的 javascript 可以在一些初始化设置之后调用 ready 函数,例如:
<script src="my-document-ready.js"></script>" <script> // 做一些初始化设置. $(document).ready(initPage); // or $(initPage); initPage函数在外部文件中 </script>
5、不要把事件直接写在 HTML 元素上,这样不方便调试:
<a id="myLink" href="#" onclick="myEventHandler();">my link</a> <!-- 差-->
$('#myLink').on('click', myEventHandler) // 好
6、尽可能的给事件加上命名空间。这样方便解除绑定,而不影响该 DOM 元素的其他事件:
$('#myLink').on('click.mySpecialClick', myEventHandler) // 好 // 之后,很容易的解除绑定 $('#myLink').unbind('click.mySpecialClick')
AJAX#
1、使用.ajax()
,避免.getJson()
或者.get()
,它们在内部也是调用.ajax()
的。
2、不要在https
的站点上请求http
,使用依赖协议的 URL
3、不要把数据加在 url 上,使用 data 属性。
// 可读性差 $.ajax({ url: "something.php?param1=test1¶m2=test2", .... }); // 可读性好 $.ajax({ url: "something.php", data: { param1: test1, param2: test2 } });
4、指定 dataType 属性,更容易知道数据类型。
5、对于 ajax 加载的内容,使用委托绑定事件,这样可以在元素不存在的时候执行绑定。(之后 ajax 加载进 DOM 结构中)
$('#parent-container').on('click', 'a', delegatedClickHandlerForAjax)
6、使用 Promise
$.ajax({ ... }).then(successHandler, failureHandler); // 或者 var jqxhr = $.ajax({ ... }); jqxhr.done(successHandler); jqxhr.fail(failureHandler);
7、抽象出 ajax 模板,方便复用:
var jqxhr = $.ajax({ url: url, type: 'GET', // default is GET but you can use other verbs based on your needs. cache: true, // default is true, but false for dataType 'script' and 'jsonp', so set it on need basis. data: {}, // add your request parameters in the data object. dataType: 'json', // specify the dataType for future reference jsonp: 'callback', // only specify this to match the name of callback parameter your API is expecting for JSONP requests. statusCode: { // if you want to handle specific error codes, use the status code mapping settings. 404: handler404, 500: handler500, }, }) jqxhr.done(successHandler) jqxhr.fail(failureHandler)
动画效果#
1、Adopt a restrained and consistent approach to implementing animation functionality(大意:采取受限制的和统一的方法来实现动画功能。)
2、满足用户体验即可,不要做过多的动画:
- 尽量使用简单的 show/hide,slideUp/slideDown 来切换元素
- 尽量使用 jQuery 预定义的时间间隔(durations),“slow”,“fast”或者 400(中等)
插件#
1、选择兼容性好,文档,测试齐全何社区支持好的插件。
2、检查插件在不同版本 jQuery 下的兼容性。
3、任何参加的可复用的组件,都应该以插件的形式实现。
链式调用#
1、使用链式调用代替变量缓存和多次调用选择器:
$('#myDiv').addClass('error').show()
2、当链式调用超过 3 级的时候,适当的换行增加可读性:
$('#myLink') .addClass('bold') .on('click', myClickHandler) .on('mouseover', myMouseOverHandler) .show()
3、链太长的时候,缓存中间对象是可以接受的。
其他#
1、参数尽量使用对象形式:
$myLink.attr('href', '#').attr('title', 'my link').attr('rel', 'external') // 差, 调用三次attr() // 好, 调用一次 $myLink.attr({ href: '#', title: 'my link', rel: 'external', })
2、尽量不要把 css 混在 js 中:
$('#mydiv').css({ color: red, 'font-weight': 'bold' }) // 差
.error { color: red; font-weight: bold; } /* 好*/
$('#mydiv').addClass('error') // 好
3、不要使用过时的方法,注意新版更新时弃用的方法,不要使用它们。
4、必要的时候使用原生 js,这里看查看性能对比 http://jsperf.com/document-getelementbyid-vs-jquery/3
$('#myId') // 还是有一点点点点慢... document.getElementById('myId')
就这么多,技术有限,翻译的不妥的地方,欢迎留言指出!