作為 Nettuts+ 的編輯,我可以審查提交的教程中的大量代碼。盡管 jquery 已經推出多年,但我仍然最常看到一個常見的錯誤。
示例#1
考慮以下代碼:
$('.nav a').click(function() { $(this).hide(); $(this).css('color', 'red'); $(this).show(); alert('something else'); $(this).hide(); return false; });
由于多種原因,上面的代碼過于復雜。不要擔心代碼實際上做了什么(它是胡言亂語)。相反,我希望您查看所有對 $(this) 的引用。
將 dom 視為一個池。
將 DOM 視為一個池。還記得小時候,你會跳進水池里尋找硬幣,而你的父母卻表現得好像在旁邊看著嗎?這將是我們在現實世界中的比較。
每次使用 $(‘.someClass’) 時,jQuery 都會跳轉到池 (DOM) 中,并搜索該硬幣(或節點)。因此,當您在一個函數中多次引用它時,就會需要大量的潛水。或者,從現實世界的比較來看,這是浪費且不必要的。如果不需要,為什么要調用 jQuery?您應該執行我們所說的“緩存”。
$('.nav a').click(function(e) { var anchor = $(this); anchor .hide() .css('color', 'red') .show(); alert('something else'); anchor.hide(); e.preventDefault(); });
這樣就干凈多了。雖然現在現代瀏覽器引擎的速度快得令人難以置信,并且會盡可能地彌補你糟糕的編碼,但你仍然應該努力編寫高效的代碼,并避免浪費所有精力在池中跳躍。現在,從技術上講,如果您向 jQuery 傳遞一個 DOM 節點,例如 this,它不會重新查詢 DOM。它只是返回一個 jQuery 對象。
老實說,因為兩者之間的性能差異可以忽略不計,所以我們為自己編寫了干凈的代碼。
示例 2
讓我們考慮一個稍微復雜一點的例子:選項卡。
$('.tabs li').css('position', 'relative'); $('.tabs li').click(function() { $('.tabs li').removeClass('active'); $(this).addClass('active'); $(this).load('someHref', function() {} ); // example $(this).css('top', '1px'); });
這個代碼到處都是。它很丑陋,而且效率低下。第一個解決辦法是擺脫所有 CSS。如果值是動態創建的,則只能在 JavaScript 中放置樣式。例如,如果您需要計算元素在屏幕上的精確位置,您可以使用 .css(‘left’,calculatedValue)。在這種情況下,可以將其全部導出到外部樣式表。這給我們留下了:
$('.tabs li').click(function() { $('.tabs li').removeClass('active'); $(this).load('someHref', function() {} ); // example $(this).addClass('active'); });
接下來,我們為什么要繼續在 DOM 中查詢 .tabs li 和 $(this)?別再在泳池里跳了。讓我們“緩存” .tabs li 的位置。
var tabs = $('.tabs li'); tabs.click(function() { tabs.removeClass('active'); $(this).load('someHref', function() {} ); // example $(this).addClass('active'); });
更好了,但我們仍然調用 $(this) 兩次,這沒什么大不了的。但是,根據我的經驗,如果不盡早將其消滅在萌芽狀態,這個數字很快就會增加。
var tabs = $('.tabs li'); tabs.click(function() { var tab = $(this); tabs.removeClass('active'); tab.addClass('active') .load('someHref', function() {} ); // example });
過濾
另一個(優化程度稍差)選項是使用過濾。
var tabs = $('.tabs li'); tabs.click(function() { tabs.removeClass('active') .Filter(this) .addClass('active') .load('someHref', function() {} ); // example });
本例的不同之處在于,我們不是引用 $(this),而是使用 filter() 方法將列表項的集合減少到僅單擊的項.
你應該拿走什么
是的,如果您在函數中多次引用 $(‘.tabs) ,世界不會終結。如今 JavaScript 引擎速度非常快。如果您要測試數千次這樣做的性能,執行的差異可能是幾百毫秒。但問題仍然存在:你為什么要這么做?
有時,當我們使用像 jQuery 這樣的大量抽象時,很容易忘記 $(‘.tabs’) 是一個運行大量代碼的實際函數。還應該注意的是,這些概念通常適用于 JavaScript,而不僅僅是 jQuery。
使用上述 caching 技術為自己編寫更清晰的代碼。