国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

angular2 臟檢查series1-Zone.js

0x584a / 926人閱讀

摘要:并不是真正的進入,而是通過包裹的方式偽造執行上下文,并通過鉤子函數方便的進入執行環境。如何使用運行結果可以從上面的看到運用提供的,鉤子函數方便的進入了執行的上下文,記錄了時間。我們還有個需求,需要因人而異的處理這些暴露的鉤子函數。

angular2 臟檢查總述

這系列文章將介紹angular2的臟值檢查是如何工作的?如何比ng1更高效?帶著上述問題,讓我們一起來看看angular2這禽獸(誰讓它叫angular,又那么生猛)干了什么。

什么是臟值檢查

片面的說臟檢查是對比當前的數據和曾經的數據是否發生改變。而在這個context下,我想介紹的是angular2從發現數據的變化到找到變化的點到更新DOM的整個過程。也就是說這里所說的臟值檢查是Viewmodel與view層的那座橋梁。先看下面的圖,紅色表示改變的節點。

那么問題來了,angular2是如何知道數據發生了改變?又是如何知道需要修改DOM的位置,準確的最小范圍的修改DOM呢?沒錯,盡可能小的范圍修改DOM,因為操作DOM對于性能來說可是一件奢侈品。別急,讓我們先看看沒有angular我們如何實現數據改變到view的改變。在web古老的年代,那個asp.net、j2ee、php的時代,請求+整頁重繪,那時啪啪啪的重繪聲,如今依然回蕩在心中,痛苦不可磨滅。再來看看SPA時代,其它framework的解決方案,最值得一提的是名聲在外的react用了diff虛擬DOM的方式,也實現了最小化更新DOM。有興趣可以看看Tero的這篇博客,比較了很多流行框架對這個問題的解決。
http://teropa.info/blog/2015/...
回到上面問題,angular2是如何知道數據發生了改變?細心的你可能會發現,在angular2 示例項目中都引入了一個Zone.js的東西。Zone.js是什么鬼?

angular2 臟檢查Series1之Zone.js Zone能做什么?

Zone提供方便的方式”進入”異步函數執行上下文(注意進入有引號,后面解釋),并能在異步執行環境中加入一些鉤子的東西。
為什么需要進入異步函數的執行上下文?這是我看到zone.js的github的第一個問題。我們先來看看這樣一個場景。

foo();
setTimeout(doSomething, 2000);
bar();
baz();

我任性的提出一個問題,我想知道上面doSomething函數在這個上下文中什么時候開始執行的?要知道為了不阻塞UI界面的用戶體驗,在JavaScript執行的很多耗時操作都被封裝為了異步操作,如:setTimeout、XMLHttpRequest、DOM事件等。也就是說doSomething會進入事件循環。 這個時候是不是特別期望,能進入doSomething的執行環境,拿到點證據控告寫doSomething這個函數的程序員寫得垃圾?可能你已經想到了解決辦法,雖然doSomething的執行上下文我進不了。但我可以wrap一下doSomething偽造一個執行上下文,在這個上下文中做點手腳,哼哼.. 恭喜你,你已經有了和Zone.js團隊成員一樣的思想覺悟。
這也是為什么上面提到的Zone提供方便的方式”進入”異步函數執行上下文中進入加了引號。并不是真正的進入,而是通過包裹的方式偽造執行上下文,并通過鉤子函數方便的進入執行環境。這個場景看似有些極端,但在異步Task跟蹤,分析,錯誤記錄、開發調試跟蹤等場景,都有這樣的需求。下面我們來看看Zone是如何提供方便的。

Zone如何使用

demo1

var profilingZone = (function () {
    var time = 0,
        timer = performance ?
                    performance.now.bind(performance) :
                    Date.now.bind(Date);
    return {
      beforeTask: function () {
        this.start = timer();
        console.log(‘beforeTask time:’+this.start);
      },
      afterTask: function () {
        time += timer() - this.start;
        console.log(‘afterTask time:’+time);
      }
    };
  }());

zone.fork(profilingZone).run(function(){
foo();
setTimeout(doSomething, 2000);
bar();
baz();
});

demo1運行結果

// beforeTask time:3073872.9000000004
// AfterTask time:1.04500000039116
// beforeTask time:3075873.165
// AfterTask time:1.2550000004

可以從上面的demo看到運用Zone提供的beforeTask,afterTask鉤子函數方便的進入了doSomething執行的上下文,記錄了時間。值得一提的是,我們并沒有對doSomething做任何處理,我們所做的只是在doSomething外部做了點改動。就達到了進入doSomething執行上下文的目的。似乎看到了AOP的思想(說到AOP我又想到了ng2的annotation,找個時間好好分享一下)。 除此之外Zone還提供了一些其它鉤子函數。請參考:https://github.com/angular/zo...

Zone原理

yo! check it out! demo的運行結果為什么會有輸出兩次beforeTask和AfterTask?要想解答這個問題,我們先來看看Zone運行的原理。前面提到過Zone偽造一個執行上下文,實際上Zone有一個叫猴子補丁的東西。在Zone.js運行時,就會為這些異步事件做一層代理包裹,也就是說Zone.js運行后,調用setTimeout、addEventListener等瀏覽器異步事件時,不再是調用原生的方法,而是被猴子補丁包裝過后的代理方法。wo!猴子補丁真牛逼,它是怎么把這些原生的事件都進行包裝改造后進化成“猴子”的呢?其實很簡單,其實并不難..只需要暴力點!再暴力點!

//以下是Zone.js啟動時執行邏輯的抽象代碼片段
function zoneAwareAddEventListener() {...}
function zoneAwareRemoveEventListener() {...}
function zoneAwarePromise() {...}
function patchTimeout() {...}
window.prototype.addEventListener = zoneAwareAddEventListener;
window.prototype.removeEventListener = zoneAwareRemoveEventListener;
window.prototype.promise = zoneAwarePromise;
window.prototype.setTimeout = patchTimeout;

確實很暴力,直接原生覆蓋了!原生的異步方法都被代理覆蓋了,代理里setup了鉤子函數,這還不能完全解決問題。我們還有個需求,需要“因人而異”的處理這些暴露的鉤子函數。例如

setTimeout(doA, 2000);
setTimeout(doB, 2000);

這里有兩個方法doA和doB,總不能用鉤子函數里只能做同樣的事情吧。所以會有一個根zone和fork。fork可以擴展一個新的zone。而每個zone都有自己的生命周期。為了理解這個問題我們再來看個Demo

demo2

//fork一個新的zone,我們給它暫定個名字叫temporary zone.
Zone.current.fork({}).run(function () {
    //調用beforeTask等鉤子(zone內部處理)
    //run 內部Zone.current指向temporary zone(zone內部做的處理),并添加一個inTheZone屬性設置為true.
    Zone.current.inTheZone = true;
    //調用被猴子補丁包裝后的setTimeout方法,并將包裝后的greet方法內部的zone設置成當前的temporary zone,并將函數greet加入事件循環.
    setTimeout(function greet() {
        console.log("in the zone: " + !!Zone.current.inTheZone);
    }, 0);
    //要在zone run中執行的內容已經執行完了,調用AfterTask鉤子.(zone內部處理)
    //    //調用afterTask等鉤子.(zone內部處理)
    //zone.current引用替換成根zone,因為run外部的zone不應該是fork后的zone,fork后的zone生命周期隨著run的結束而結束.(zone內部處理)
});

console.log("in the zone: " + !!Zone.current.inTheZone);

demo2輸出結果

in the zone: false
in the zone: true

希望更好的理解,我在demo中加了注釋以說明zone生命周期的問題.我們可以看到fork后的temporary zone生命周期隨著run執行的結束而結束.所以run外部的console.log取不到Zone.current里的屬性inTheZone(temporary zone中的inTheZone)而在greet真正執行時,也會經歷和run內部一樣的過程(鉤子函數的執行,zone的引用替換銷毀等).而包裹后的greet內部的zone指向的是在setTimeout傳入greet上下文中的(當前作用域中)temporary zone.
現在再回頭看看demo1中為什么會輸出兩次beforeTask和AfterTask,也正是因為zone特定的生命周期所造成的.

Zone.js在angular2中的運用

還記得大明湖畔ng1的$scope.$apply嗎?任何原生的事件都不會觸發臟檢查,必須得調用$scope.$apply來告訴angular。我的數據有更新了,你同步更新下UI吧。而在angular2中有了Zone.js。原生隨便用,setTimeout,addEventListener、promise等都在ngZone中執行,angular并在ngZone中setup了相應的鉤子,通知angular2做相應的臟檢查處理,然后更新DOM。

如何臟檢查?如何更新DOM?比起angular1有什么新的變化?下章再見。希望上述內容能給你一些幫助。如有任何疑問與不足,歡迎指出并討論。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80322.html

相關文章

  • Angular 2.x+ 檢查機制理解

    摘要:策略減少檢測次數當輸入屬性不變時,可以跳過整個變更檢測子樹。現在當執行更改檢測時,它將從上到下進行。并且一旦更改檢測運行結束,它將恢復整個樹的狀態。 Angular 2.x+ 臟檢查機制理解 目前幾種主流的前端框架都已經實現雙向綁定特性,但實現的方法各有不同: 發布者-訂閱者模式(backbone.js) 臟值檢查(angular.js) 數據劫持 + 發布者-訂閱者模式(vue.j...

    W4n9Hu1 評論0 收藏0
  • 尋找真兇Echarts or Angular

    摘要:我們再來看一下調用棧,如下圖從圖中我們發現了一個調用棧的代碼執行過,還記得里提到嗎發起臟檢查的通知者,它代理了原生事件,任何一個原生異步事件的觸發都會導致的運行。 尋找真兇Echarts or Angular 這是一篇故事,就如同技術,我們所追求的不是一個結局,而是那些深受啟發與共鳴的過程,那是我們成長的經驗與生產力的積淀! 故事開始于瘋了的ionic3應用 頁面打開,什么也沒做5s里...

    sumory 評論0 收藏0
  • angular2初入眼簾之-搭個環境

    angular2是什么?我猜不容我贅述,各位一定略有耳聞,無論是曾經AngularJS的擁躉,亦或是React的粉絲,都或多或少的對她有過一點了解。未見其物、先聞其聲,angular2在問世之前已經做足了宣傳,想必諸位也一定被下面各種詞匯所震懾,什么:TypeScript、 ES5、 ES6、 Dart、 Immutable、 Unidirectional Data Flow、 Reactive ...

    everfight 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<