angularJs项目实战!04:angularjs的性能问题
上一篇文章中我花了很多口舌去介紹angularjs是一個(gè)中型框架,面對(duì)大型應(yīng)用時(shí)少不了第三方類庫的配合。而我的核心議題是:如何以angularjs的思路使用其他類庫,這里jquery是最好的例子了,誰讓它爭(zhēng)議最大。許多人一看到j(luò)query就火冒三丈沖過來覺得這貨是影響代碼結(jié)構(gòu)、打破angular way的純潔的罪魁禍?zhǔn)?#xff0c;但事實(shí)是好的木匠總是會(huì)允許爛木頭的存在,何況jquery并非爛木頭。只要配合得當(dāng)jquery完全可以做你項(xiàng)目中的小伙伴,而如果不改變傳統(tǒng)的思路,就算用了angularjs你的代碼也不容易維護(hù)。
不過對(duì)于angularjs本身來說,以上這個(gè)問題純粹是使用者的理念和設(shè)計(jì)方法的問題,并不重要。重要的問題是,angularjs是個(gè)中型框架,做一個(gè)大型應(yīng)用,往大了講功能略顯不足(比如缺少好用的UI插件和異步模塊載入機(jī)制),往小了說又不夠靈活(例如不能無縫與第三方路由整合)。但這些都不是最要命的。功能不足用第三方類庫補(bǔ)嘛,不夠靈活就學(xué)會(huì)適應(yīng)吧,但最要命的問題是,性能效率問題。
怎么個(gè)性能效率問題呢?你可以自己測(cè)試一下:在一個(gè)頁面上搞500+個(gè)不同的ng-model,然后看看頁面的渲染效率會(huì)低到什么程度就知道了。
有人會(huì)說,誰沒事干在一個(gè)頁面上搞那么多ng-model啊!這肯定是寫頁面的人模塊沒有劃分好!但事實(shí)是,這種情況很容易出現(xiàn),例如,在顯示一個(gè)angularjs實(shí)現(xiàn)的長(zhǎng)列表的時(shí)候。
我大半年前曾經(jīng)歡喜于angularjs的特性,而苦于沒有一個(gè)好的基于angularjs的grid(表格)插件,于是自己動(dòng)手瞎寫了一個(gè),叫anGrid. 代碼已經(jīng)很久沒有維護(hù)了。但是還能用。 各位大爺輕噴。https://github.com/zhangdiwaa/anGrid
這個(gè)程序一開始運(yùn)行無誤,在顯示20行X11列的列表(約造成了250個(gè)ng-model)毫無問題,反應(yīng)也很快。配合angularjs的過濾器,排序、替換圖標(biāo)什么的就是手到擒來啊!
但問題很快發(fā)生了,我用了一個(gè)測(cè)試數(shù)據(jù),造成了大約250行X11列的大列表(約造成了2900個(gè)ng-model),結(jié)果這個(gè)列表在chrome瀏覽器下居然渲染了20秒才出來,我還以為電腦死機(jī)了。測(cè)試了很多次都是如此。我認(rèn)為是自己代碼寫的太爛。直到我做了1000+的ng-model測(cè)試,和看了同學(xué)侯振宇的博客以及angularjs源碼才覺悟過來,其實(shí)angularjs也不是十全十美的。
Talk is cheap,我們直接來看內(nèi)部實(shí)現(xiàn)吧。
angularjs雙向綁定的核心是$digest方法。這個(gè)函數(shù)會(huì)直接檢測(cè)“所有的數(shù)據(jù)模型”是否改動(dòng),有改動(dòng)就去更新相應(yīng)的視圖元素。但事實(shí)上,看了源碼我們就會(huì)發(fā)現(xiàn)這個(gè)$digest方法執(zhí)行效率不會(huì)高。3重大循環(huán)嚇?biāo)廊?#xff0c;還要監(jiān)聽同步。連大神自己都在代碼注釋里吐槽說:yes,this code is a bit crazy.
$digest方法,請(qǐng)注意注釋部分,中間有刪截(感謝侯振宇的截圖)
對(duì)于這個(gè)性能問題,只有換個(gè)框架才能改變。
我的同學(xué)侯振宇他們所在的團(tuán)隊(duì),為此專門搞了個(gè)全新的MVVM框架avalon,性能超過angularjs 10倍——ng-model超過1萬都很快。原理是將數(shù)據(jù)模型中的屬性用get 和set 方法重寫。在set方法中去更新所有和當(dāng)前數(shù)據(jù)模型有關(guān)的視圖元素,這就是為什么avalon一更新數(shù)據(jù)就能馬上反映到視圖上、并且性能更出眾的原因。直接翻到avalon源碼的“modelFactory”函數(shù),在這個(gè)函數(shù)中avalon收集和當(dāng)前模型有關(guān)的視圖元素、其他相關(guān)聯(lián)的數(shù)據(jù),最后注冊(cè)到屬性中。其中更詳細(xì)的原理可以直接參考作者 司徒正美 的github https://github.com/RubyLouvre/avalon
那如果不想換掉angularjs怎么辦?那就努力把每頁的ng-model控制在500以下吧。就上面那個(gè)angularjs實(shí)現(xiàn)gird表格插件的問題,其實(shí)用點(diǎn)“hack”方法也能搞定。假設(shè)要顯示250行X11列的gird表格,那么就顯示20行的元素和滾動(dòng)條,讓其他的元素不渲染不顯示。只有當(dāng)滾動(dòng)條向下滑的時(shí)候才渲染新的元素,同時(shí)消除舊的元素。更進(jìn)一步的還可以檢測(cè)滾動(dòng)條滾動(dòng)的速度,滾動(dòng)得慢就一行一行得預(yù)渲染,滾動(dòng)得快就在停下的時(shí)候預(yù)渲染。如此就能始終把ng-model的數(shù)量控制在一個(gè)可以接受的范圍內(nèi)了。(嘛,這不就跟angular ui 里的ng-grid一樣了嗎!)
來源:?http://community.angular.cn/A0gy
來自為知筆記(Wiz)
總結(jié)
以上是生活随笔為你收集整理的angularJs项目实战!04:angularjs的性能问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: salt-ssh 安装salt-mini
- 下一篇: Ybquery项目部署idea