AngularJS進(jìn)行性能調(diào)優(yōu)的7個建議
AnglarJS作為一款優(yōu)秀的Web框架,可大大簡化前端開發(fā)的負(fù)擔(dān)。近日Sebastian Fröstl在一篇博文《AngularJS Performance Tuning for Long Lists》中表示AnglarJS在處理包含復(fù)雜數(shù)據(jù)結(jié)構(gòu)的大型列表時,其運(yùn)行速度會非常慢。他在文中同時分享了解決方案。下面為該文的譯文。
AnglarJS很棒,但當(dāng)處理包含復(fù)雜數(shù)據(jù)結(jié)構(gòu)的大型列表時,其運(yùn)行速度就會非常慢。這是我們將核心管理頁面遷移到AngularJS過程中遇到的問題。這些頁面在顯示500行數(shù)據(jù)時本應(yīng)該工作順暢,但首個方法的渲染時間竟花費(fèi)了7秒,太可怕了。
后來,我們發(fā)現(xiàn)了在實(shí)現(xiàn)過程中存在兩個主要性能問題。一個與“ng-repeat ”指令有關(guān),另一個與過濾器有關(guān)。
下文將分享我們通過不同的方法解決性能問題的經(jīng)驗,希望可以給你帶來啟示。
一、AngularJS 中的ng-repeat在處理大型列表時,速度為什么會變慢?
AngularJS中的ng-repeat在處理2500個以上的雙向數(shù)據(jù)綁定時速度會變慢。這是由于AngularJS通過“dirty checking”函數(shù)來檢測變化。每次檢測都會花費(fèi)時間,所以包含復(fù)雜數(shù)據(jù)結(jié)構(gòu)的大型列表將降低你應(yīng)用的運(yùn)行速度。
二、提高性能的先決條件
時間記錄指令
為了測量一個列表渲染所花費(fèi)的時間,我們寫了一個簡單的程序,通過使用“ng-repeat”的屬性“$last”來記錄時間。時間存放在TimeTracker服務(wù)中,這樣時間記錄就與服務(wù)器端的數(shù)據(jù)加載分開了。
// Post repeat directive for logging the rendering time angular.module('siApp.services').directive('postRepeatDirective', ['$timeout', '$log', 'TimeTracker', function($timeout, $log, TimeTracker) { return function(scope, element, attrs) { if (scope.$last){ $timeout(function(){ var timeFinishedLoadingList = TimeTracker.reviewListLoaded(); var ref = new Date(timeFinishedLoadingList); var end = new Date(); $log.debug("## DOM rendering list took: " + (end - ref) + " ms"); }); } }; } ]); // Use in HTML: …
Chrome開發(fā)者工具的時間軸(Timeline)屬性
在Chrome開發(fā)者工具的時間軸標(biāo)簽中,你可以看見事件、每秒內(nèi)瀏覽器幀數(shù)和內(nèi)存分配?!癿emory”工具用來檢測內(nèi)存泄漏,及頁面所需的內(nèi) 存。當(dāng)幀速率每秒低于30幀時就會出現(xiàn)頁面閃爍問題?!癴rames”工具可幫助了解渲染性能,還可顯示出一個JavaScript任務(wù)所花費(fèi)的CPU時 間。
三、通過限制列表的大小進(jìn)行基本的調(diào)優(yōu)
緩解該問題,最好的辦法是限制所顯示列表的大小??赏ㄟ^分頁、添加無限滾動條來實(shí)現(xiàn)。
分頁
分頁,我們可以使用AngularJS的“l(fā)imitTo”過濾器(AngularJS1.1.4版本以后)和“startFrom”過濾器??梢酝ㄟ^限制顯示列表的大小來減少渲染時間。這是減少渲染時間最高效的方法。
// Pagination in controller $scope.currentPage = 0; $scope.pageSize = 75; $scope.numberOfPages = function() { return Math.ceil($scope.displayedItemsList.length/ $scope.pageSize); }; // Start from filter angular.module('app').filter('startFrom', function() { return function(input, start) { return input.slice(start); }; // Use in HTML // Pagination buttons{{$index + 1}}
如果你不能/不想使用分頁,但過濾過程又很慢,這時一定要檢查前五步,并使用“ng-show”隱藏掉多余的列表元素。
無限滾動條
如果你希望進(jìn)一步了解該方法,可訪問 http://binarymuse.github.io/ngInfiniteScroll/
四、七大調(diào)優(yōu)法則
1. 渲染沒有數(shù)據(jù)綁定的列表
這是最明顯的解決方案,因為數(shù)據(jù)綁定是性能問題最可能的根源。如果你只想顯示一次列表,并不需要更新、改變數(shù)據(jù),放棄數(shù)據(jù)綁定是絕佳的辦法。不過可惜的是,你會失去對數(shù)據(jù)的控制權(quán),但除了該法,我們別無選擇。進(jìn)一步了解: https://github.com/Pasvaz/bindonce。
2.不要使用內(nèi)聯(lián)方法計算數(shù)據(jù)
為了在控制器中直接過濾列表,不要使用可獲得過濾鏈接的方法?!皀g-repeat”會評估每個 [$digest(http://docs.angularjs.org/api/ng.$rootScope.Scope#$digest)%5D表達(dá)式。在我們的案例中,“filteredItems()”返回過濾鏈接。如果評估過程很慢,它將迅速降低整個應(yīng)用的速度。
//這并不是一個好方法,因為要頻繁地評估。
//這是要采用的方法
3.使用兩個列表(一個用來進(jìn)行視圖顯示,一個作為數(shù)據(jù)源)
將要顯示的列表與總的數(shù)據(jù)列表分開,是非常有用的模型。你可以對一些過濾進(jìn)行預(yù)處理,并將存于緩存中的鏈接應(yīng)用到視圖上。下面案例展示了基本實(shí)現(xiàn)過程。filteredLists變量保存著緩存中的鏈接,applyFilter方法來處理映射。
/* Controller */ // Basic list var items = [{name:"John", active:true }, {name:"Adam"}, {name:"Chris"}, {name:"Heather"}]; // Init displayedList $scope.displayedItems = items; // Filter Cache var filteredLists['active'] = $filter('filter)(items, {"active" : true}); // Apply the filter $scope.applyFilter = function(type) { if (filteredLists.hasOwnProperty(type){ // Check if filter is cached $scope.displayedItems = filteredLists[type]; } else { /* Non cached filtering */ } } // Reset filter $scope.resetFilter = function() { $scope.displayedItems = items; } /* View */Select active
{{item.name}}
4.在其他模板中使用ng-if來代替ng-show
如果你用指令、模板來渲染額外的信息,例如通過點(diǎn)擊來顯示列表項的詳細(xì)信息,一定要使用 ng-if(AngularJSv. 1.1.5以后)。ng-if可阻止渲染(與ng-show相比)。所以其它DOM和數(shù)據(jù)綁定可根據(jù)需要進(jìn)行評估。
以上內(nèi)容給大家詳解了AngularJS進(jìn)行性能調(diào)優(yōu)的7個建議,希望大家喜歡。
相關(guān)文章
Angular2學(xué)習(xí)筆記之?dāng)?shù)據(jù)綁定的示例代碼
本篇文章主要介紹了Angular2學(xué)習(xí)筆記之?dāng)?shù)據(jù)綁定的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Angular設(shè)計模式hierarchical?injector實(shí)現(xiàn)代碼復(fù)用模塊化
這篇文章主要為大家介紹了Angular設(shè)計模式hierarchical?injector實(shí)現(xiàn)代碼復(fù)用模塊化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
angular 實(shí)現(xiàn)同步驗證器跨字段驗證的方法
幾乎每個web應(yīng)用都會用到表單,那么驗證器就是必不可少的東西,這篇文章主要介紹了angular 實(shí)現(xiàn)同步驗證器跨字段驗證的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-04-04
AngularJS基礎(chǔ)學(xué)習(xí)筆記之控制器
在AngularJS中,控制器是一個Javascript函數(shù)(類型/類),用來增強(qiáng)除了根作用域意外的作用域?qū)嵗摹.?dāng)你或者AngularJS本身通過<code>scope.$new</code>倆創(chuàng)建一個新的子作用域?qū)ο髸r,有一個選項能讓你將它當(dāng)做參數(shù)傳遞給控制器。2015-05-05
Angular實(shí)現(xiàn)搜索框及價格上下限功能
這篇文章主要為大家詳細(xì)介紹了Angular實(shí)現(xiàn)搜索框及價格上下限功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
Angular 4.x中表單Reactive Forms詳解
這篇文章主要介紹了Angular 4.x中表單Reactive Forms的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-04-04
詳解Angular.js的$q.defer()服務(wù)異步處理
相信大家都知道jquery和angular都有defer服務(wù),這篇文章暫以angular為例談?wù)剛€人的理解,在文章的最后并附上jquery的阮一峰總結(jié)的defer。有需要的朋友們也可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧。2016-11-11
Angular實(shí)現(xiàn)下載安裝包的功能代碼分享
本文通過實(shí)例代碼給大家介紹了angular實(shí)現(xiàn)下載安裝包的功能以及基于angularjs代碼實(shí)現(xiàn)錨點(diǎn)跳轉(zhuǎn)的功能,需要的朋友參考下吧2017-09-09
AngularJS開發(fā)教程之控制器之間的通信方法分析
這篇文章主要介紹了AngularJS開發(fā)教程之控制器之間的通信方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了AngularJS控制器之間通信的三種常用方式及相關(guān)使用技巧,需要的朋友可以參考下2016-12-12
angularjs 表單密碼驗證自定義指令實(shí)現(xiàn)代碼
這篇文章主要介紹了angularjs 表單密碼驗證自定義指令實(shí)現(xiàn)代碼,需要的朋友可以參考下2016-10-10

