>  기사  >  웹 프론트엔드  >  jQueryperformance_jquery에 대한 몇 가지 최적화 제안

jQueryperformance_jquery에 대한 몇 가지 최적화 제안

WBOY
WBOY원래의
2016-05-16 15:45:231076검색

루프에서 매번 배열의 길이 속성에 액세스하지 말고 루프가 시작되기 전에 캐시하세요.

var myLength = myArray.length;

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

루프 외부에서 추가 작업 수행

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'); // 嗯,快多了

이벤트 프록시 사용

이벤트 프록시를 사용하면 이벤트가 컨테이너의 모든 요소(예: 목록 요소 li)가 아닌 컨테이너(예: 순서가 지정되지 않은 목록 ul)에 바인딩될 수 있습니다. $.fn.live 및 $.fn.delegate는 모두 이벤트를 컨테이너에 바인딩하지만 $.fn.delegate는 가능한 한 많이 사용해야 하며 결국 명확한 컨텍스트($.fn.live 문서의 컨텍스트와 비교)를 사용해야 합니다. )은 훨씬 작으므로 불필요한 필터링을 많이 피할 수 있습니다.

성능 향상 외에도 이벤트에 바인딩된 컨테이너에 새 요소를 추가하면 이러한 새 요소를 이벤트에 다시 바인딩할 필요가 없다는 점도 장점입니다.

// 不好 (如果列表元素非常多,你就悲剧了)
$('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에서 DOM에서 요소를 언로드한 다음 작업이 완료된 후 DOM에 추가할 수 있는 $.fn.detach 메서드를 도입했습니다.

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

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

외부 스타일 시트를 사용하여 많은 요소의 스타일 수정

$.fn.css를 사용하여 20개 이상의 요소에 대한 스타일을 수정하는 경우 페이지에 직접 스타일 태그를 추가하는 것을 고려해야 합니다. 이렇게 하면 성능이 60% 향상된다고 합니다.

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

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

$.fn.data 대신 $.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]) { ... }

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.