jQuery的陷阱,以避免

我正在用jQuery开始一个项目。

你在jQuery项目中有什么陷阱/错误/误解/滥用/误用?

不知道性能命中和过度使用select器,而不是将它们分配给局部variables。 例如:-

$('#button').click(function() { $('#label').method(); $('#label').method2(); $('#label').css('background-color', 'red'); }); 

而不是:-

 $('#button').click(function() { var $label = $('#label'); $label.method(); $label.method2(); $label.css('background-color', 'red'); }); 

或者更好地链接 :

 $('#button').click(function() { $("#label").method().method2().css("background-color", "red"); }); 

当我意识到调用堆栈是如何工作的时候,我发现了这个启发性的时刻。

编辑:纳入意见build议。

了解如何使用上下文。 通常情况下,一个jQueryselect器将search整个文档:

 // This will search whole doc for elements with class myClass $('.myClass'); 

但是你可以通过在上下文中search来加快速度:

 var ct = $('#myContainer'); // This will search for elements with class myClass within the myContainer child elements $('.myClass', ct); 

不要使用裸类select器,如下所示:

 $('.button').click(function() { /* do something */ }); 

这将最终看每一个元素,看看它是否有一个“button”类。

相反,你可以帮助它,例如:

 $('span.button').click(function() { /* do something */ }); $('#userform .button').click(function() { /* do something */ }); 

去年,我从Rebecca Murphy的博客里了解到这一点

更新 – 这个答案是2年前给出的,并不正确的当前版本的jQuery。 其中一个评论包括一个testing来certificate这一点。 还有一个更新版本的testing ,包括在这个答案时jQuery的版本。

尝试拆分匿名函数,以便可以重用它们。

 //Avoid $('#div').click( function(){ //do something }); //Do do function divClickFn (){ //do something } $('#div').click( divClickFn ); 
  • 避免滥用文件准备好。
  • 保持文档准备好仅用于初始化代码。
  • 始终在文档之外提取function,以便可以重复使用。

我已经看到数百行的代码在文档就绪语句。 丑陋,不可读,不可能维护。

使用$.ajax函数向服务器发送Ajax请求时,应该避免使用complete事件来处理响应数据。 它会触发请求是否成功。

而不是complete ,使用success

请参阅文档中的Ajax事件 。

“链接”animation事件与callback。

假设你想要点击一个段落消失animation。 之后您也想从DOM中删除元素。 你可能会认为你可以简单地链接方法:

 $("p").click(function(e) { $(this).fadeOut("slow").remove(); }); 

在这个例子中,.remove()会在.fadeOut()完成之前被调用,破坏渐变效果,并且简单的让元素瞬间消失。 相反,如果只想在完成前一个命令时触发一个命令,请使用callback函数:

 $("p").click(function(e){ $(this).fadeOut("slow", function(){ $(this).remove(); }); }); 

.fadeOut()的第二个参数是一个匿名函数,它会在.fadeOut()animation完成后运行。 这使得逐渐衰落,并随后去除元素。

不要滥用插件。

大多数情况下,你只需要库和用户界面。 如果保持简单,那么从长远来看,代码是可以维护的。 不是所有的插件都支持和维护,实际上大多数都不是。 如果您可以使用核心元素模仿function,我强烈推荐它。

插件很容易插入你的代码中,为你节省一些时间,但是当你需要额外的东西时,修改它们是一个坏主意,因为你失去了可能的更新。 您在开始时保存的时间稍后将会更改已弃用的插件。

select明智使用的插件。 除了库和用户界面,我还经常使用$ .cookie , $ .form , $ .validate和thickbox 。 其余的我主要开发自己的插件。

如果绑定多次相同的事件,则会多次触发。 我通常总是去解unbind('click').bind('click')只是为了安全

陷阱:使用循环代替select器。

如果您发现自己正在使用jQuery的“.each”方法遍历DOM元素,请问自己是否可以使用select器来获取元素。

有关jQueryselect器的更多信息:
http://docs.jquery.com/Selectors

陷阱:不要使用像Firebug这样的工具

萤火虫实际上是用于这种debugging。 如果你打算在Javascript中使用DOM,那么你需要一个像Firebug这样的好工具来给你提供可见性。

有关Firebug的更多信息: http : //getfirebug.com/

其他伟大的想法是在这个多态播客的插曲:(与戴夫病区的jQuery秘密) http://polymorphicpodcast.com/shows/jquery/

误解在正确的上下文中使用这个标识符。 例如:

 $( "#first_element").click( function( event) { $(this).method( ); //referring to first_element $(".listOfElements").each( function() { $(this).someMethod( ); // here 'this' is not referring first_element anymore. }) }); 

在这里你可以解决它的一个例子:

 $( "#first_element").click( function( event) { $(this).method( ); //referring to first_element var $that = this; $(".listOfElements").each( function() { $that.someMethod( ); // here 'that' is referring to first_element still. }) }); 

避免search整个DOM几次。 这是真的可以延迟你的脚本。

坏:

 $(".aclass").this(); $(".aclass").that(); ... 

好:

 $(".aclass").this().that(); 

坏:

 $("#form .text").this(); $("#form .int").that(); $("#form .choice").method(); 

好:

 $("#form") .find(".text").this().end() .find(".int").that().end() .find(".choice").method(); 

总是将$(this)caching到一个有意义的variables,特别是在.each()

喜欢这个

 $(selector).each(function () { var eachOf_X_loop = $(this); }) 

类似于Repo Man所说的,但不完全。

在开发ASP.NET winforms时,我经常这样做

 $('<%= Label1.ClientID %>'); 

忘记#号。 正确的forms是

 $('#<%= Label1.ClientID %>'); 

活动

 $("selector").html($("another-selector").html()); 

不克隆任何事件 – 你必须重新绑定所有事件。

根据JP的评论 – 克隆()如果传递true,则重新确认事件。

避免多次创build相同的jQuery对象

 //Avoid function someFunc(){ $(this).fadeIn(); $(this).fadeIn(); } //Cache the obj function someFunc(){ var $this = $(this).fadeIn(); $this.fadeIn(); } 

我也对JavaScript说这个,但jQuery,JavaScript应该永远不会取代CSS。

此外,请确保该网站可用于JavaScriptclosures的人(今天不如今天相关,但总是很好,有一个完全可用的网站)。

做太多的DOM操作。 虽然.html(),.append(),.prepend()等方法很好,但由于浏览器渲染和重新渲染页面的方式,经常使用它们会导致速度变慢。 将html作为string创build并将其包含到DOM中通常会更好,而不是多次更改DOM。

代替:

 var $parent = $('#parent'); var iterations = 10; for (var i = 0; i < iterations; i++){ var $div = $('<div class="foo-' + i + '" />'); $parent.append($div); } 

尝试这个:

 var $parent = $('#parent'); var iterations = 10; var html = ''; for (var i = 0; i < iterations; i++){ html += '<div class="foo-' + i + '"></div>'; } $parent.append(html); 

甚至这个($ wrapper是一个新创build的元素还没有被注入到DOM中,附加节点到这个包装div不会导致速度下降,最后我们追加$ wrapper到$ parent,只使用一个DOM操作):

 var $parent = $('#parent'); var $wrapper = $('<div class="wrapper" />'); var iterations = 10; for (var i = 0; i < iterations; i++){ var $div = $('<div class="foo-' + i + '" />'); $wrapper.append($div); } $parent.append($wrapper); 

使用ClientID获取ASP.NET项目中控件的“真实”标识。

 jQuery('#<%=myLabel.ClientID%>'); 

另外,如果您在SharePoint中使用jQuery,则必须调用jQuery.noConflict()。

将ID代替jQuery对象传递给函数:

 myFunc = function(id) { // wrong! var selector = $("#" + id); selector.doStuff(); } myFunc("someId"); 

传递一个包装更灵活:

 myFunc = function(elements) { elements.doStuff(); } myFunc($("#someId")); // or myFunc($(".someClass")); etc. 

链接过度使用。

看到这个:

 this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true); 

说明

使用string累加器样式

使用+运算符会在内存中创build一个新的string,并将连接的值分配给它。 只有在这之后,结果才会分配给一个variables。 为避免连接结果的中间variables,可以使用+ =运算符直接指定结果。 慢:

 a += 'x' + 'y'; 

更快:

 a += 'x'; a += 'y'; 

基本操作可能比函数调用更快

考虑在性能关键的循环和函数中使用替代的原始操作。 慢:

 var min = Math.min(a, b); arr.push(val); 

更快:

 var min = a < b ? a : b; arr[arr.length] = val; 

阅读更多JavaScript性能最佳实践

如果您希望用户在浏览器中查看html实体,请使用“html”而不是“text”来插入Unicodestring,如下所示:

 $('p').html("Your Unicode string") 

我的两美分)

通常,使用jquery意味着您不必担心实际的DOM元素。 你可以写这样的东西 – $('div.mine').addClass('someClass').bind('click', function(){alert('lalala')}) – 这个代码会执行而不会抛出任何错误。

在某些情况下,这在某些情况下是非常有用的 – 完全不是,但事实上,jquery往往是空的,友好的。 然而, replaceWith会抛出一个错误,如果试图用一个不属于该文档的元素来使用它。 我觉得这相当直观。

在我看来,另一个缺陷是prevAll()方法返回的节点顺序 – $('<div><span class="A"/><span class="B"/><span class="C"/><span class="D"/></div>').find('span:last-child').prevAll() 实际上并不是什么大不了的,但是我们应该牢记这个事实。

如果你计划在很多数据中使用Ajax,比如说,包含20列的1500行数据表,那么千万不要想到使用jQuery将这些数据插入到你的HTML中。 使用普通的JavaScript。 jQuery在较慢的机器上速度太慢。

此外,一半的时间jQuery会做的事情,会导致它慢,就像试图parsing传入HTML中的脚本标签,并处理浏览器的怪癖。 如果你想快速插入速度,坚持使用普通的JavaScript。

在一个小项目中使用jQuery,只需要几行普通的JavaScript即可完成。

不理解事件绑定。 JavaScript和jQuery的工作方式不同。

以大众需求为例,

在jQuery中:

 $("#someLink").click(function(){//do something}); 

没有jQuery:

 <a id="someLink" href="page.html" onClick="SomeClickFunction(this)">Link</a> <script type="text/javascript"> SomeClickFunction(item){ //do something } </script> 

基本上JavaScript所需的钩子不再是必要的。 即使用内联标记(onClick等),因为您可以简单地使用开发人员通常用于CSS目的的ID和类。