優(yōu)化

2018-06-17 16:27 更新
    

在開(kāi)發(fā)時(shí),避免在同一流程內(nèi)多次使用setData當(dāng)然是最佳實(shí)踐。采取人工維護(hù)肯定是能夠?qū)崿F(xiàn)的,就好比能用原生 js 能寫出比眾多框架更高效的性能一樣。但當(dāng)頁(yè)面邏輯負(fù)責(zé)起來(lái)之后,花很大的精力去維護(hù)都不一定能保證每個(gè)流程只存在一次setData,而且可維護(hù)性也不高。因此,WePY選擇使用臟檢查去做數(shù)據(jù)綁定優(yōu)化。用戶不用再擔(dān)心在我的流程里,數(shù)據(jù)被修改了多少次,只會(huì)在流程最后做一次臟檢查,并且按需執(zhí)行setData。

臟檢測(cè)機(jī)制借鑒自AngularJS,多數(shù)人一聽(tīng)到臟檢查都會(huì)覺(jué)得是低效率的一種作法,認(rèn)為使用 Vue.js 中的 getter,setter更高效。其實(shí)不然,兩種機(jī)制都是對(duì)同一件事的不同實(shí)現(xiàn)方式。各有優(yōu)劣,取決于使用的人在使用過(guò)程中是否正好放大了機(jī)制中的劣勢(shì)面。

WePY 中的 setData 就好比是一個(gè) setter,在每次調(diào)用時(shí)都會(huì)去渲染視圖。因此如果再封裝一層 getter、setter 就完全沒(méi)有意義,沒(méi)有任何優(yōu)化可言。這也就是為什么一個(gè)類 Vue.js 的小程序框架卻選擇了與之相反的另外一種數(shù)據(jù)綁定方式。

再回來(lái)看臟檢查的問(wèn)題在哪里,從上面實(shí)驗(yàn)的代碼可以看出,臟檢查的性能問(wèn)題在于每次進(jìn)行臟檢查時(shí),需要遍歷所以數(shù)據(jù)并且作值的深比較,性能取決于遍歷以及比較數(shù)據(jù)的大小。WePY 中深比較是使用的 underscore 的 isEqual 方法。為了驗(yàn)證效率問(wèn)題,使用不同的比較方法對(duì)一個(gè) 16.7 KB 的復(fù)雜 JSON 數(shù)據(jù)進(jìn)行深比較,測(cè)試用例請(qǐng)看這里:deep-compare-test-case

得到的結(jié)果如下:

圖片描述

從結(jié)果來(lái)看,對(duì)于一個(gè) 16.7 KB 的數(shù)據(jù)深比較是完全不足以產(chǎn)生性能問(wèn)題的。那 AngularJS 1.x 臟檢查的性能問(wèn)題是怎么出現(xiàn)的呢?

AngularJS 1.x 中沒(méi)有組件的概念,頁(yè)面數(shù)據(jù)就位于 controller 的 $scope 當(dāng)中。每一次臟檢查都是從 $rootScope 開(kāi)始,隨后遍歷至所有子 $scope。參考這里 angular.js:L1081。對(duì)于一個(gè)大型的單頁(yè)應(yīng)用來(lái)說(shuō),所有 $scope 中的數(shù)據(jù)可能達(dá)到了上百甚至上千個(gè)都有可能。那時(shí),臟檢查的每次遍歷就可能真的會(huì)成為了性能的瓶頸了。

反觀 WePY,使用類似于 Vue.js 的組件化開(kāi)發(fā),在拋開(kāi)父子組件雙向綁定通信的情況下,組件的臟檢查僅針對(duì)組件本身的數(shù)據(jù)進(jìn)行,一個(gè)組件的數(shù)據(jù)通常不會(huì)太多,數(shù)據(jù)太多時(shí)可以細(xì)化組件劃分的粒度。因此在這種情況下,臟檢查并不會(huì)導(dǎo)致性能問(wèn)題。

其實(shí),在很多情況下,框架封裝的解決方案都不是性能優(yōu)化的最優(yōu)解決方案,使用原生肯定能優(yōu)化出更快的代碼。但它們之所以存在并且有價(jià)值,那都是因?yàn)樗鼈兪窃谛阅?、開(kāi)發(fā)效率、可維護(hù)性上尋找到一個(gè)平衡點(diǎn),這也是為什么 WePY 選擇使用臟檢查作為數(shù)據(jù)綁定的優(yōu)化。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)