淺析AngularJS中的生命週期和延遲處理

來源:互聯網
上載者:User

   這篇文章主要介紹了淺析AngularJS中的生命週期和延遲處理,是AngularJS中較為核心的深層次內容,需要的朋友可以參考下

  這裡,我們再討論一些常用的進階的控制反轉容器(Inversion of Control containers):消極式載入(lazy-loading),生命週期管理(lifetime management),以及延遲的建立/處理(deferred creation/resolution)。

  消極式載入(Lazy-Loading)

  所謂消極式載入就是當你需要用到對象時候才對其進行執行個體化。許多依賴注入系統都會在一開始就建立組件,作為它的可依賴項目。不過有時候,直到在應用中用到它們之前,你都不會想去執行個體化這些組件。Angular 中,一個很好的例子就是,當你在配置的時候去設定一個行為,而該行為又會引用到一些還沒建立的組件。

  假設你想攔截系統內建的 $log 服務,因此你把它存在了 $rootScope 裡面。當然我不建議這樣做,不過這樣舉例比較簡單有效。為了攔截,你在配置的時候用到了 $provide 然後調用修飾方法。如果這時你想直接引用 $rootScope 的話,由於循環參考你會拿到個異常。而解決案是通過 $injector 消極式載入 $rootScope 。

  下面的代碼只會在 $rootScope 第一次被使用的時候才去載入它。

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 $provide.decorator(, [, , ($delegate, $injector) { log = $delegate.log.bind($delegate); $delegate.log = (msg) { rs = $injector.get(); (rs.logs === undefined) { rs.logs = []; } rs.logs.push(msg); log(msg); }; $delegate; }]);

  之後的調用都會拿到一樣的單例 $rootScope。 這裡有個可用例子。我之前好像聽過有個(不對的)說法(Angular 只支援單例) … 當然不是真的。$injector 中的方法就是用來給你管理你的組件的生命週期的。

  生命週期管理

  生命週期涉及到你如何管理組件的執行個體。預設情況,當你注入一個 Angular 的依賴,依賴注入就會幫你建立它的一個副本然後在你的應用裡面重用它。大多數情況下這確實是我們所期待的。而有些情況下,會要求同一組件的多個執行個體。假設下面的計數服務:

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Counter($log) { $log.log(); }   angular.extend(Counter.prototype, { count: 0, increment: () { .count += 1; .count; } });   Counter.$inject = [];   app.service(, Counter);

  你的應用要跟蹤不同的計數器。而你注入該服務後,總會拿到一樣的計數器。這難道是 Angular 的限制?

  當然不是。重複一次,通過 $injector 服務你可以在任何時候建立一個新副本。下面的代碼用了兩個獨立的計數器:

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 app.run([, , , (rs, c, i) { rs.count = c.count; rs.update = c.increment; rs.update2 = () { c = i.instantiate(Counter); rs.count2 = c.count; rs.update2 = () { c.increment(); rs.count2 = c.count; }; }; }]);

  你可以看到計數器都是被獨立的執行個體跟蹤的,這裡是可用例子。如果你需要經常產生新執行個體,你可以像這樣註冊服務:

  ?

1 2 3 4 5 6 7 8 app.factory(, [, (i) { { getCounter: () { i.instantiate(Counter); } }; }]);

  產生一個需要的執行個體就是那麼簡單,而且你可以用你的工廠組件來代替 $injector:

  ?

1 2 3 4 5 6 7 8 9 10 11 app.run([, , (rs, cf) { c1 = cf.getCounter(), c2 = cf.getCounter(); rs.count = c1.count; rs.update = c1.increment; rs.count2 = c2.count; rs.update2 = () { rs.count2 = c2.increment(); }; }]);

  你可以看看這個完整版本的可用例子。如你所見,用 Angular 的內建依賴注入是完全有可能管理你組件的生命週期的。那延遲處理(deferred resolution)又怎樣呢 – 比如說,有些組件你需要在 Angular 已經配置好之後引入,而且需要用它們的依賴來封裝起來。

  延遲處理(Deferred Resolution)

  我們已經介紹了在 Angular 中可以延遲處理依賴的一種方法。當你想封裝某些東西的時候,你可以調用 $injector 服務的 instantiate ,然後它可以通過參數嗅探來解決依賴,看起來就像用 $inject 的靜態屬性一樣,或者也可以通過檢查你傳給它的數組來實現的。也就是說,下面這個是完全有效寫法:

  ?

1 $injector.instantiate(['dependency', Constructor]);

  你還可以調用帶裝飾數組的方法。假設你有一個方法依賴於 $log 服務,你可以運行時通過延遲處理來調用它,像下面這樣:

  ?

1 2 3 4 myFunc = [, ($log) { $log.log(); }]; $injector.invoke(myFunc);

  你可以看看這個可用例子(開啟你的控制台,看看你按下按鈕之後發生了什麼)。

  總結

  綜上所述,Angular 的依賴注入提供了許多進階特性,你在商業應用生產線上會希望並且經常會用到它們。factories, services, 和 providers 的便捷讓 Angular 開發人員常常產生錯覺,認為這裡只有唯一選項可用。而神奇之處在於 $injector 服務,你可以用它產生所需的單例,建立新的組件或者動態引用帶依賴的方法。

  最後要注意的是,你用戶端代碼裡面的注入即使在 Angular 之外也是可用的。我們來看一個在 Angular 之外封裝的,通過注入調用 $log 服務的例子,點這裡。為什麼要把 ‘ng' 傳入方法的數組?它是 Angular 的核心模組,當你封裝你的模組的時候是會被隱式添加的,但是如果你的指令要產生自己的注入執行個體的時候,你就必須顯式添加了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.