摘要:通常寫代碼時(shí)我們無需主動調(diào)用或是因?yàn)樵谕獠繉ξ覀兊幕卣{(diào)函數(shù)做了包裝。類似的不只是這些事件回調(diào)函數(shù),還有等。常量依舊會重復(fù)檢查。會檢查中有沒有一個(gè)名為的成員。
TL;DR
臟檢查是一種模型到視圖的數(shù)據(jù)映射機(jī)制,由 $apply 或 $digest 觸發(fā)。
臟檢查的范圍是整個(gè)頁面,不受區(qū)域或組件劃分影響
使用盡量簡單的綁定表達(dá)式提升臟檢查執(zhí)行速度
盡量減少頁面上綁定表達(dá)式的個(gè)數(shù)(單次綁定和ng-if)
給 ng-repeat 添加 track by 讓 angular 復(fù)用已有元素
什么是臟數(shù)據(jù)檢查(Dirty checking)Angular 是一個(gè) MVVM 前端框架,提供了雙向數(shù)據(jù)綁定。所謂雙向數(shù)據(jù)綁定(Two-way data binding)就是頁面元素變化會觸發(fā) View-model 中對應(yīng)數(shù)據(jù)改變,反過來 View-model 中數(shù)據(jù)變化也會引發(fā)所綁定的 UI 元素?cái)?shù)據(jù)更新。操作數(shù)據(jù)就等同于操作 UI。
看似簡單,其實(shí)水很深。UI 元素變化引發(fā) Model 中數(shù)據(jù)變化這個(gè)通過綁定對應(yīng) DOM 事件(例如 input 或 change)可以簡單的實(shí)現(xiàn);然而反過來就不是那么容易。
比如有如下代碼:
用戶點(diǎn)擊了 button,angular 執(zhí)行了一個(gè)叫 onClick 的方法。這個(gè) onClick 的方法體對于 angular 來說是黑盒,它到底做了什么不知道。可能改了 $scope.content1 的值,可能改了 $scope.content2 的值,也可能兩個(gè)值都改了,也可能都沒改。
那么 angular 到底應(yīng)該怎樣得知 onClick() 這段代碼后是否應(yīng)該刷新 UI,應(yīng)該更新哪個(gè) DOM 元素?
angular 必須去挨個(gè)檢查這些元素對應(yīng)綁定表達(dá)式的值是否有被改變。這就是臟數(shù)據(jù)檢查的由來(臟數(shù)據(jù)檢查以下簡稱臟檢查)。
臟檢查如何被觸發(fā)angular 會在可能觸發(fā) UI 變更的時(shí)候進(jìn)行臟檢查:這句話并不準(zhǔn)確。實(shí)際上,臟檢查是 $digest](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest) 執(zhí)行的,另一個(gè)更常用的用于觸發(fā)臟檢查的函數(shù) [$apply 其實(shí)就是 $digest 的一個(gè)簡單封裝(還做了一些抓異常的工作)。
通常寫代碼時(shí)我們無需主動調(diào)用 $apply 或 $digest 是因?yàn)?angular 在外部對我們的回調(diào)函數(shù)做了包裝。例如常用的 ng-click,這是一個(gè)指令(Directive),內(nèi)部實(shí)現(xiàn)則 類似 于
DOM.addEventListener("click", function ($scope) { $scope.$apply(() => userCode()); });
可以看到:ng-click 幫我們做了 $apply 這個(gè)操作。類似的不只是這些事件回調(diào)函數(shù),還有 $http、$timeout 等。我聽很多人抱怨說 angular 這個(gè)庫太大了什么都管,其實(shí)你可以不用它自帶的這些服務(wù)(Service),只要你記得手工調(diào)用 $scope.$apply。
臟檢查的范圍前面說到:angular 會對所有綁定到 UI 上的表達(dá)式做臟檢查。其實(shí),在 angular 實(shí)現(xiàn)內(nèi)部,所有綁定表達(dá)式都被轉(zhuǎn)換為 $scope.$watch()。每個(gè) $watch 記錄了上一次表達(dá)式的值。有 ng-bind="a" 即有 $scope.$watch("a", callback),而 $scope.$watch 可不會管被 watch 的表達(dá)式是否跟觸發(fā)臟檢查的事件有關(guān)。
例如:
問:點(diǎn)擊 TEST 這個(gè)按鈕時(shí)會觸發(fā)臟檢查嗎?觸發(fā)幾次?
首先:ng-click="" 什么都沒有做。angular 會因?yàn)檫@個(gè)事件回調(diào)函數(shù)什么都沒做就不進(jìn)行臟檢查嗎?不會。
然后:#span1 被隱藏掉了,會檢查綁定在它上面的表達(dá)式嗎?盡管用戶看不到,但是 $scope.$watch("content", callback) 還在。就算你直接把這個(gè) span 元素干掉,只要 watch 表達(dá)式還在,要檢查的還會檢查。
再次:重復(fù)的表達(dá)式會重復(fù)檢查嗎?會。
最后:別忘了 ng-show="false"。可能是因?yàn)?angular 的開發(fā)人員認(rèn)為這種綁定常量的情況并不多見,所以 $watch 并沒有識別所監(jiān)視的表達(dá)式是否是常量。常量依舊會重復(fù)檢查。
所以:
答:觸發(fā)三次。一次 false,一次 content,一次 content
所以說一個(gè)綁定表達(dá)式只要放在當(dāng)前 DOM 樹里就會被監(jiān)視,不管它是否可見,不管它是否被放在另一個(gè) Tab 里,更不管它是否與用戶操作相關(guān)。
另外,就算在不同 Controller 里構(gòu)造的 $scope 也會互相影響,別忘了 angular 還有全局的 $rootScope,你還可以 $scope.$emit。angular 無法保證你絕對不會在一個(gè) controller 里更改另一個(gè) controller 生成的 scope,包括 自定義指令(Directive)生成的 scope 和 Angular 1.5 里新引入的組件(Component)。
所以說不要懷疑用戶在輸入表單時(shí) angular 會不會監(jiān)聽頁面左邊導(dǎo)航欄的變化。
臟檢查與運(yùn)行效率臟檢查慢嗎?
說實(shí)話臟檢查效率是不高,但是也談不上有多慢。簡單的數(shù)字或字符串比較能有多慢呢?十幾個(gè)表達(dá)式的臟檢查可以直接忽略不計(jì);上百個(gè)也可以接受;成百上千個(gè)就有很大問題了。綁定大量表達(dá)式時(shí)請注意所綁定的表達(dá)式效率。建議注意一下幾點(diǎn):
表達(dá)式(以及表達(dá)式所調(diào)用的函數(shù))中少寫太過復(fù)雜的邏輯
不要連接太長的 filter(往往 filter 里都會遍歷并且生成新數(shù)組)
不要訪問 DOM 元素。
使用單次綁定減少綁定表達(dá)式數(shù)量單次綁定(One-time binding 是 Angular 1.3 就引入的一種特殊的表達(dá)式,它以 :: 開頭,當(dāng)臟檢查發(fā)現(xiàn)這種表達(dá)式的值不為 undefined 時(shí)就認(rèn)為此表達(dá)式已經(jīng)穩(wěn)定,并取消對此表達(dá)式的監(jiān)視。這是一種行之有效的減少綁定表達(dá)式數(shù)量的方法,與 ng-repeat 連用效果更佳(下文會提到),但過度使用也容易引發(fā) bug。
善用 ng-if 減少綁定表達(dá)式的數(shù)量如果你認(rèn)為 ng-if 就是另一種用于隱藏、顯示 DOM 元素的方法你就大錯(cuò)特錯(cuò)了。
ng-if 不僅可以減少 DOM 樹中元素的數(shù)量(而非像 ng-hide 那樣僅僅只是加個(gè) display: none),每一個(gè) ng-if 擁有自己的 scope,ng-if 下面的 $watch 表達(dá)式都是注冊在 ng-if 自己 scope 中。當(dāng) ng-if 變?yōu)?false,ng-if 下的 scope 被銷毀,注冊在這個(gè) scope 里的綁定表達(dá)式也就隨之銷毀了。
考慮這種 Tab 選項(xiàng)卡實(shí)現(xiàn):
對于這種會反復(fù)隱藏、顯示的元素,通常人們第一反應(yīng)都是使用 ng-show 或 ng-hide 簡單的用 display: none 把元素設(shè)置為不可見。
然而入上文所說,肉眼不可見不代表不會跑臟檢查。如果將 ng-show 替換為 ng-if 或 ng-switch-when
[[Tab 1 body...]][[Tab 2 body...]][[Tab 3 body...]][[Tab 4 body...]]
有如下優(yōu)點(diǎn):
首先 DOM 樹中的元素個(gè)數(shù)顯著減少至四分之一,降低內(nèi)存占用
其次 $watch 表達(dá)式也減少至四分之一,提升臟檢查循環(huán)的速度
如果這個(gè) tab 下面有 controller(例如每個(gè) tab 都被封裝為一個(gè)組件),那么僅當(dāng)這個(gè) tab 被選中時(shí)該 controller 才會執(zhí)行,可以減少各頁面的互相干擾
如果 controller 中調(diào)用接口獲取數(shù)據(jù),那么僅當(dāng)對應(yīng) tab 被選中時(shí)才會加載,避免網(wǎng)絡(luò)擁擠
當(dāng)然也有缺點(diǎn):
DOM 重建本身費(fèi)時(shí)間
如果 tab 下有 controller,那么每次該 tab 被選中時(shí) controller 都會被執(zhí)行
如果在 controller 里面調(diào)接口獲取數(shù)據(jù),那么每次該 tab 被選中時(shí)都會重新加載
各位讀者自己取舍。
當(dāng)臟檢查遇上數(shù)組ng-repeat!這就更有(e)趣(xin)了。通常的綁定只是去監(jiān)聽一個(gè)值的變化(綁定對象也是綁定到對象里的某個(gè)成員),而 ng-repeat 卻要監(jiān)視一整個(gè)數(shù)組對象的變化。例如有:
會生成 4 個(gè) li 元素
1
2
3
4
沒有問題。如果我添加一個(gè)按鈕如下:
請考慮:當(dāng)用戶點(diǎn)擊這個(gè)按鈕會發(fā)生什么?
我們一步一步分析。開始的時(shí)候,angular 記錄了 array 的初始狀態(tài)為:
[ { "value": 1 }, { "value": 2 }, { "value": 3 }, { "value": 4 } ]
當(dāng)用戶點(diǎn)擊按鈕后,數(shù)組的第一個(gè)元素被刪除了,array 變?yōu)椋?/p>
[ { "value": 2 }, { "value": 3 }, { "value": 4 } ]
兩者比較:
array.length = 4 => array.length = 3
array[0].value = 1 => array[0].value = 2
array[1].value = 2 => array[1].value = 3
array[2].value = 3 => array[2].value = 4
array[3].value = 4 => array[3].value = undefined (array[4] 為 undefined,則 undefined.value 為 undefined,見 Angular 表達(dá)式的說明)
如同你所見:angular 經(jīng)過比較,看到的是:
數(shù)組長度減少了 1
數(shù)組第 1 個(gè)元素的 value 被改為 2
數(shù)組第 2 個(gè)元素的 value 被改為 3
數(shù)組第 3 個(gè)元素的 value 被改為 4
反應(yīng)到 DOM 元素上就是:
第 1 個(gè) li 內(nèi)容改為 2
第 2 個(gè) li 內(nèi)容改為 3
第 3 個(gè) li 內(nèi)容改為 4
第 4 個(gè) li 刪掉
可以看到,刪除一個(gè)元素導(dǎo)致了整個(gè) ul 序列的刷新。要知道 DOM 操作要比 JS 變量操作要慢得多,類似這樣的無用操作最好能想辦法避免。
那么問題出在哪里呢?用戶刪除了數(shù)組的第一個(gè)元素,導(dǎo)致了整個(gè)數(shù)組元素前移;然而 angular 沒法得知用戶做了這樣一個(gè)刪除操作,只能傻傻的按下標(biāo)一個(gè)一個(gè)比。
那么只要引入一種機(jī)制來標(biāo)記數(shù)組的每一項(xiàng)就好了吧。于是 angular 引入了 track by
詳解 track by用來標(biāo)記數(shù)組元素的一定是數(shù)組里類似 ID 的某個(gè)值。這個(gè)值一定要符合以下這兩個(gè)特點(diǎn)。
不能重復(fù)。ID 重復(fù)了什么鬼
值一定要簡單。ID 是用于比較相等的,有時(shí)候由于算法不同可能還要比較大小,處于速度考慮不能太復(fù)雜。
基于這兩個(gè)特點(diǎn)。如果用戶沒有給 ng-repeat 指定 track by 的表達(dá)式,則默認(rèn)為內(nèi)置函數(shù) $id。$id 會檢查 item 中有沒有一個(gè)名為 $$hashKey` 的成員。如有,返回其值;如沒有,則生成一個(gè)新的唯一值寫入。這就是數(shù)組中那個(gè)奇怪的 `$$hashKey 成員來歷,默認(rèn)值是 "object:X"(你問我為什么是個(gè)字符串而不是數(shù)字?我怎么知道。。。)
還是前面的問題,引入 track by 后再來看。因?yàn)闆]有指定 track by,則默認(rèn)為 $id(item),實(shí)際為 $$hashKey。
開始的時(shí)候,$id(item) 給數(shù)組中所有項(xiàng)創(chuàng)建了 $$hashKey
這時(shí) angular 記錄了 array 的初始狀態(tài)為:
[ { "value": 1, "$$hashKey": "object:1" }, { "value": 2, "$$hashKey": "object:2" }, { "value": 3, "$$hashKey": "object:3" }, { "value": 4, "$$hashKey": "object:4" } ]
當(dāng)用戶點(diǎn)擊按鈕后,數(shù)組的第一個(gè)元素被刪除了,array 變?yōu)椋?/p>
[ { "value": 2, "$$hashKey": "object:2" }, { "value": 3, "$$hashKey": "object:3" }, { "value": 4, "$$hashKey": "object:4" } ]
先比較 track by 的元素,這里為 $id(item),即 $$hashKey
"object:1" => "object:2"
"object:2" => "object:3"
"object:3" => "object:4"
"object:4" => undefined
兩者對不上,說明數(shù)組被做了增刪元素或者移動元素的操作。將其規(guī)整
"object:1" => undefined
"object:2" => "object:2"
"object:3" => "object:3"
"object:4" => "object:4"
那么顯然,第一個(gè)元素被刪除了。再比較剩余的元素
array[0].value = 2 => array[0].value = 2
array[1].value = 3 => array[1].value = 3
array[2].value = 4 => array[2].value = 4
結(jié)論是:
原數(shù)組第一個(gè)元素被刪除
其他沒變
angular 通過將新舊數(shù)組的 track by 元素做 diff 猜測用戶的行為,最大可能的減少 DOM 樹的操作,這就是 track by 的用處。
默認(rèn) track by 的坑So far so good! 然而需求某天有變,程序員小哥決定用 filter 給數(shù)組做 map 后再渲染。
map 定義如下:
xxModule.filter("map", function () { return arr => arr.map(item => ({ value: item.value + 1 })); });
ng-repeat 執(zhí)行時(shí)先計(jì)算表達(dá)式 array | myMap 的值:
arrayForNgRepeat = [ { value: 2 }, { value: 3 }, { value: 4 }, { value: 5 }, ]
注意數(shù)組 arrayForNgRepeat 和原來的數(shù)組 array 不是同一個(gè)引用,因?yàn)?filter 里的 map 操作生成了一個(gè)新數(shù)組,每一項(xiàng)都是新對象,跟原數(shù)組無關(guān)。
ng-repeat 時(shí),angular 發(fā)現(xiàn)用戶沒有指定 track by,按照默認(rèn)邏輯,使用 $id(item) 作為 track by,添加 $$hashKey
arrayForNgRepeat = [ { value: 2, "$$hashKey": "object:1" }, { value: 3, "$$hashKey": "object:2" }, { value: 4, "$$hashKey": "object:3" }, { value: 5, "$$hashKey": "object:4" }, ]
生成 DOM:
2
3
4
5
這里請?jiān)俅巫⒁猓簲?shù)組 arrayForNgRepeat 與原始數(shù)組 array 沒有任何關(guān)系,數(shù)組本身是不同的引用,數(shù)組里的每一項(xiàng)也是不同引用。修改新數(shù)組的成員不會影響到原來的數(shù)組。
這時(shí) array 的值:
array = [ { value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }, ]
這時(shí)用戶的某個(gè)無關(guān)操作觸發(fā)了臟檢查。針對 ng-repeat 表達(dá)式,首先計(jì)算 array | myMap 的值:
newArrayForNgRepeat = [ { value: 2 }, { value: 3 }, { value: 4 }, { value: 5 }, ]
先比較 track by 的元素。用戶沒有指定,默認(rèn)為 $id(item)。
$id 發(fā)現(xiàn)數(shù)組中有一些元素沒有 $$hashKey`,則給它們填充新 `$$hashKey,結(jié)果為
newArrayForNgRepeat = [ { value: 2, "$$hashKey": "object:5" }, { value: 3, "$$hashKey": "object:6" }, { value: 4, "$$hashKey": "object:7" }, { value: 5, "$$hashKey": "object:8" }, ]
這時(shí)兩邊的 track by 的實(shí)際結(jié)果為
"object:1" => "object:5"
"object:2" => "object:6"
"object:3" => "object:7"
"object:4" => "object:8"
兩者對不上,說明數(shù)組被做了增刪元素或者移動元素的操作。將其規(guī)整
"object:1" => undefined
"object:2" => undefined
"object:3" => undefined
"object:4" => undefined
undefined => "object:5"
undefined => "object:6"
undefined => "object:7"
undefined => "object:8"
結(jié)論是:
原數(shù)組全部 4 個(gè)元素被刪除
新添加了 4 個(gè)元素
于是 angular 把原來所有 li 刪除,再創(chuàng)建 4 個(gè)新的 li 元素,填充它們的 textContent,放到 ul 里
如果懷疑我說的話,請自己在瀏覽器里測試。你可以清楚的看到調(diào)試工具里 DOM 樹的閃爍
track by 與性能不恰當(dāng)?shù)?ng-repeat 會造成 DOM 樹反復(fù)重新構(gòu)造,拖慢瀏覽器響應(yīng)速度,造成頁面閃爍。除了上面這種比較極端的情況,如果一個(gè)列表頻繁拉取 Server 端數(shù)據(jù)自刷新的話也一定要手工添加 track by,因?yàn)榻涌诮o前端的數(shù)據(jù)是不可能包含 $$hashKey 這種東西的,于是結(jié)果就造成列表頻繁的重建。
其實(shí)不必考慮那么多,總之加上沒壞處,至少可以避免 angular 生成 $$hashKey 這種奇奇怪怪的東西。所以
請給 ng-repeat 手工添加 track by!
重要的事情再說一遍
請給 ng-repeat 手工添加 track by!
通常列表都是請求接口從數(shù)據(jù)庫中讀取返回的。通常數(shù)據(jù)庫中的記錄都有一個(gè) id 字段做主鍵,那么這時(shí)使用 id 作為 track by 的字段是最佳選擇。如果沒有,可以選擇一些業(yè)務(wù)字段但是確保不會重復(fù)的。例如一個(gè)連表頭都是動態(tài)生成的表格,表頭就可以使用其字段名作為 track by 的字段(對象的 key 是不會重復(fù)的)。
如果真的找不到用于 track by 的字段,讓 angular 自動生成 $$hashKey 也不是不可以,但是切記檢查有沒有出現(xiàn) DOM 元素不斷重刷的現(xiàn)象,除了仔細(xì)看調(diào)試工具的 DOM 樹是否閃爍之外,給列表中的元素添加一個(gè)特別的標(biāo)記(比如 style="background: red"),也是一個(gè)行之有效的方法(如果這個(gè)標(biāo)記被意外清除,說明原來的 DOM 元素被刪除了)。
除非真的沒辦法,不推薦使用 $index 作為 track by 的字段。
track by 與 單次綁定 連用track by 只是讓 angular 復(fù)用已有 DOM 元素。數(shù)組每個(gè)子元素內(nèi)部綁定表達(dá)式的臟檢查還是免不了的。然而對于實(shí)際應(yīng)用場景,往往是數(shù)組整體改變(例如分頁),數(shù)組每一項(xiàng)通常卻不會多帶帶變化。這時(shí)就可以通過使用單次綁定大量減少 $watch 表達(dá)式的數(shù)量。例如
除非 track by 字段改變造成的 DOM 樹重建,item.a 等一旦顯示在頁面上后就不會再被監(jiān)視。
如果每行有 5 個(gè)綁定表達(dá)式,每頁顯示 20 條記錄,通過這種方法每頁就可以減少 5 * 20 = 100 個(gè)綁定表達(dá)式的監(jiān)視。
注意:如果在 ng-repeat 內(nèi)部使用的單次綁定,就一定不要用 track by $index。否則用戶切換下一頁頁面也不會更新。
使用分頁減少綁定個(gè)數(shù)這個(gè)就不多說了。能后端分頁的就后端分頁;接口不支持分頁的也要前端分頁;前端分頁時(shí)可以簡單的寫個(gè) filter 用 Array.prototype.slice 實(shí)現(xiàn)。
能直接減少數(shù)組中項(xiàng)的個(gè)數(shù)就不要在 ng-repeat 中每項(xiàng)上寫 ng-show 或 ng-if
寫在最后的話臟檢查這個(gè)東西,其實(shí)在三大主流前端框架中或多或少都有涉及。React 每次生成新的 Virtual DOM,與舊 Virtual DOM 的 diff 操作本來就可以看做一次臟檢查。Vue 從相對徹底的拋棄了臟檢查機(jī)制,使用 Property 主動觸發(fā) UI 更新,但是 Vue 仍然不能拋棄 track by 這個(gè)東西。
既然臟檢查在三大主流框架里或多或少都有所保留,為什么唯獨(dú) Angular 的性能被廣為詬病呢?其實(shí)還是說在 Angular 1 的機(jī)制下,臟檢查的執(zhí)行范圍過大以及頻率太過頻繁了。Angular 1.5 從 Angular 2+ 引入了組件(Component)的概念,然而形似而神非,其實(shí)只是一個(gè)特殊的 Directive 馬甲而已,并不能將臟檢查的執(zhí)行范圍限制在各個(gè)組件之內(nèi),所以并不能本質(zhì)的改變 Angular 1 臟檢查機(jī)制效率低下的現(xiàn)狀。
也許 Angular 1 終將被淘汰。但 Angular 作為前端第一個(gè) MVVM 框架,著實(shí)引發(fā)了前端框架更新?lián)Q代的熱潮。百足之蟲死而不僵,不管怎么樣我還得繼續(xù)維護(hù)停留在電腦里的 Angular 1 項(xiàng)目。不過也許老板哪天大發(fā)慈悲給我們用 Vue 重構(gòu)整個(gè)項(xiàng)目的時(shí)間,將來的事情誰知道呢?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/84515.html
摘要:通常寫代碼時(shí)我們無需主動調(diào)用或是因?yàn)樵谕獠繉ξ覀兊幕卣{(diào)函數(shù)做了包裝。類似的不只是這些事件回調(diào)函數(shù),還有等。常量依舊會重復(fù)檢查。會檢查中有沒有一個(gè)名為的成員。 TL;DR 臟檢查是一種模型到視圖的數(shù)據(jù)映射機(jī)制,由 $apply 或 $digest 觸發(fā)。 臟檢查的范圍是整個(gè)頁面,不受區(qū)域或組件劃分影響 使用盡量簡單的綁定表達(dá)式提升臟檢查執(zhí)行速度 盡量減少頁面上綁定表達(dá)式的個(gè)數(shù)(單次綁定...
摘要:本文針對的讀者具備性能優(yōu)化的相關(guān)知識雅虎條性能優(yōu)化原則高性能網(wǎng)站建設(shè)指南等擁有實(shí)戰(zhàn)經(jīng)驗(yàn)。這種機(jī)制能減少瀏覽器次數(shù),從而提高性能。僅會檢查該和它的子,當(dāng)你確定當(dāng)前操作僅影響它們時(shí),用可以稍微提升性能。 搬運(yùn)自: http://atian25.github.io/2014/05/09/angular-performace/ 不知不覺,在項(xiàng)目中用angular已經(jīng)半年多了,踩了很多坑...
摘要:我們再來看一下調(diào)用棧,如下圖從圖中我們發(fā)現(xiàn)了一個(gè)調(diào)用棧的代碼執(zhí)行過,還記得里提到嗎發(fā)起臟檢查的通知者,它代理了原生事件,任何一個(gè)原生異步事件的觸發(fā)都會導(dǎo)致的運(yùn)行。 尋找真兇Echarts or Angular 這是一篇故事,就如同技術(shù),我們所追求的不是一個(gè)結(jié)局,而是那些深受啟發(fā)與共鳴的過程,那是我們成長的經(jīng)驗(yàn)與生產(chǎn)力的積淀! 故事開始于瘋了的ionic3應(yīng)用 頁面打開,什么也沒做5s里...
摘要:來源于社區(qū),時(shí)至今日已經(jīng)基本成為的標(biāo)配了。部分很簡單,要根據(jù)傳入的執(zhí)行不同的操作。當(dāng)性能遇到瓶頸時(shí)基本不會遇到,可以更改,保證傳入數(shù)據(jù)來提升性能。當(dāng)不再能滿足程序開發(fā)的要求時(shí),可以嘗試使用進(jìn)行函數(shù)式編程。 Immutable & Redux in Angular Way 寫在前面 AngularJS 1.x版本作為上一代MVVM的框架取得了巨大的成功,現(xiàn)在一提到Angular,哪怕是已...
閱讀 2812·2019-08-30 15:55
閱讀 2858·2019-08-30 15:53
閱讀 2296·2019-08-26 13:47
閱讀 2558·2019-08-26 13:43
閱讀 3157·2019-08-26 13:33
閱讀 2805·2019-08-26 11:53
閱讀 1798·2019-08-23 18:35
閱讀 801·2019-08-23 17:16