首頁 > web前端 > js教程 > 主體

對於jQuery效能的一些最佳化建議_jquery

WBOY
發布: 2016-05-16 15:45:23
原創
1078 人瀏覽過

不要每次都在循環中存取數組的 length 屬性,應在循環開始之前就將其快取:

var myLength = myArray.length;

for (var i = 0; i < myLength; i++) {
  // do stuff
}

登入後複製

在循環外執行 append 操作

直接操作 DOM 是非常耗費性能的,尤其不要在循環中直接操作 DOM:

// 这样性能很差
$.each(myArray, function(i, item) {
  var newListItem = '<li>' + item + '</li>';
  $('#ballers').append(newListItem);
});
<p>// 这样性能较好<br />var frag = document.createDocumentFragment();</p><p>$.each(myArray, function(i, item) {<br />    var newListItem = '<li>' + item + '</li>';<br />    frag.appendChild(newListItem);<br />});<br />$('#ballers')[0].appendChild(frag);</p><p>// 这样也很好<br />var myHtml = '';</p><p>$.each(myArray, function(i, item) {<br />    html += '<li>' + item + '</li>';<br />});<br />$('#ballers').html(myHtml);</p>
登入後複製

程式碼要保持精煉

避免做重複的事情。如果你一直在做重複的事情,那就可能出問題了:

// 丑
if ($eventfade.data('currently') != 'showing') {
  $eventfade.stop();
}

if ($eventhover.data('currently') != 'showing') {
  $eventhover.stop();
}

if ($spans.data('currently') != 'showing') {
  $spans.stop();
}

// 漂亮!!
var $elems = [$eventfade, $eventhover, $spans];
$.each($elems, function(i,elem) {
  if (elem.data('currently') != 'showing') {
    elem.stop();
  }
});

登入後複製

警覺匿名函數

匿名函數滿天飛是很痛苦的事情,它們難以調試、維護、測試或複用,應盡可能的對函數命名並將其封裝在物件中,實施有效的管理:

// 不好
$(document).ready(function() {
  $('#magic').click(function(e) {
    $('#yayeffects').slideUp(function() {
      // ...
    });
  });

  $('#happiness').load(url + ' #unicorns', function() {
    // ...
  });
});

// 好
var PI = {
  onReady : function() {
    $('#magic').click(PI.candyMtn);
    $('#happiness').load(PI.url + ' #unicorns', PI.unicornCb);
  },

  candyMtn : function(e) {
    $('#yayeffects').slideUp(PI.slideCb);
  },

  slideCb : function() { ... },

  unicornCb : function() { ... }
};

$(document).ready(PI.onReady);

登入後複製

選擇器的最佳化

隨著越來越多的瀏覽器支援 document.querySelectorAll(),選擇器的重擔已經慢慢轉移給瀏覽器了,但還是有一些技巧需要注意:

優先並盡可能使用 ID 選擇器:

// 快
$('#container div.robotarm');

// 相当快
$('#container').find('div.robotarm');

使用 $.fn.find 的方式更快,因为在 $.fn.find 之前的选择器并没有使用 jQuery 自带的 Sizzle 选择器引擎,而是使用了浏览器 document.getElementById() 方法,浏览器原生的方法自然更快。

使用组合选择器时,尽可能使右端更明确,而左端不尽量不明确:

// 未优化
$('div.data .gonzalez');

// 已优化
$('.data td.gonzalez');

登入後複製

盡量在選擇器右端使用 tag.class,而左端盡可能只使用 tag 或 .class。

避免過度具體:

$('.data table.attendees td.gonzalez');

// 在不影响结果的情况下尽量删掉中间多余部分
$('.data td.gonzalez');

登入後複製

簡潔的 DOM 結構也有助於提升選擇器的效能,因為選擇器可能會少走幾層彎路去尋找那些元素。

盡量避免使用通配符,任何顯式或隱式的使用通配符,都會降低選擇器的效能:

$('.buttons > *');    // 极慢
$('.buttons').children(); // 好多了

$('.gender :radio');   // 隐式地使用通配符,慢
$('.gender *:radio');   // 显式地使用通配符,同上,慢
$('.gender input:radio'); // 嗯,快多了

登入後複製

使用事件代理

事件代理程式允許將一個事件綁定到某個容器上(例如一個無序列表 ul),而不是綁定到容器內所有元素上(例如列表元素 li)。雖說$.fn.live 和$.fn.delegate 都是將事件綁定到容器上,但是應盡可能是用$.fn.delegate,畢竟其明確的上下文(相較於$.fn.live 的上下文是document)小得多,避免了很多不必要的過濾。

除了效能方面的提升,如果為綁定了事件的容器內新增元素,那麼這些新元素就無須再次綁定事件了,這也是個優點。

// 不好 (如果列表元素非常多,你就悲剧了)
$('li.trigger').click(handlerFn);

// 好些:使用 $.fn.live 进行事件代理
$('li.trigger').live('click', handlerFn);

// 最好:使用 $.fn.delegate 进行事件代理
// 因为这样可以明确的指定一个上下文
$('#myList').delegate('li.trigger', 'click', handlerFn);

登入後複製

將元素從 DOM 卸載出來再操作

DOM 操作是比較慢的,所以應盡量避免直接操作 DOM。 jQuery 在其 1.4 版中引入了 $.fn.detach 方法,可以將元素從 DOM 中卸載出來然後進行操作,操作好了之後再添加到 DOM 中:

var $table = $('#myTable');
var $parent = $table.parent();

$table.detach();
// ... 例如这里给表格添加了很多很多行
$parent.append(table);

登入後複製

使用外部樣式表為大量元素修改樣式

當使用 $.fn.css 為超過 20 個元素修改樣式時,應考慮直接在頁面中添加 style 標籤,據說性能可提升 60%。

// 当元素少于 20 个时使用这个方法,多余 20 个时,速度就慢了
$('a.swedberg').css('color', '#asd123');

// 多余 20 个元素时,应考虑直接在页面中添加 style 标签
$('<style type="text/css">a.swedberg { color : #asd123 }</style>')
  .appendTo('head');

登入後複製

使用 $.data 取代 $.fn.data

將 $.data 應用於 DOM 元素上,比直接在選擇器上呼叫 $.fn.data 快 10 倍。當然,前提是要先明白 DOM 元素和 jQuery 結果集之間的差異。

// 速度一般
$(elem).data(key,value);

// 速度提升 10 倍
$.data(elem,key,value);

登入後複製

別在空元素上浪費時間

jQuery 不會主動告訴你,你正在一個空白的結果集上執行程式碼 – 而且執行過程中並未出錯。所以有時候再執行程式碼之前,需要先判斷一下結果集是否為空:

// 不好:执行了三个函数之后
// 才发现结果集上没有任何元素
$('#nosuchthing').slideUp();

// 好
var $mySelection = $('#nosuchthing');
if ($mySelection.length) { $mySelection.slideUp(); }

// 最好:增加一个 doOnce 插件
jQuery.fn.doOnce = function(func){
  this.length && func.apply(this);
  return this;
}

$('li.cartitems').doOnce(function(){
  // 这里可以确保结果集不是空的
});

登入後複製

這種方法特別適用於 jQuery UI 方面,因為即使結果集中不包含任何元素,其開銷也會很大。
變數的定義

可以在一條語句中定義多個變數:

// 老掉牙的写法
var test = 1;
var test2 = function() { ... };
var test3 = test2(test);

// 新写法
var test = 1,
  test2 = function() { ... },
  test3 = test2(test);

登入後複製

在自執行函數中,變數甚至可以不用定義:

(function(foo, bar) { ... })(1, 2);

登入後複製

條件判斷

// 土方法
if (type == 'foo' || type == 'bar') { ... }

// 较先进的方法
if (/^(foo|bar)$/.test(type)) { ... }

// 使用对象查找
if (({ foo : 1, bar : 1 })[type]) { ... }

登入後複製

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板