首頁 >web前端 >js教程 >淺析AngularJS中的生命週期和延遲處理_AngularJS

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

WBOY
WBOY原創
2016-05-16 15:54:061197瀏覽

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

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

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


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

 

$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 的依賴,依賴注入就會幫你創建它的一個副本然後在你的應用裡面重複使用它。大多數情況下這確實是我們所期待的。而有些情況下,會要求同一組件的多個實例。假設下面的計數服務:

 
 

Counter($log) {
  $log.log();
}
 
angular.extend(Counter.prototype, {
  count: 0,
  increment: () {
    .count += 1;
     .count;
  }
});
 
Counter.$inject = [];
 
app.service(, Counter);

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

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

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;
      };
    };
  }]);

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

app.factory(, [,
   (i) {
     {
      getCounter: () {
         i.instantiate(Counter);
      }
    };
  }]);

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

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 的靜態屬性一樣,或者也可以透過檢查你傳給它的數組來實現的。也就是說,下面這個是完全有效寫法:
 

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

你也可以呼叫有裝飾數組的方法。假設你有一個方法依賴 $log 服務,你可以運行時透過延遲處理來呼叫它,像下面這樣:

 

 myFunc = [, ($log) {
  $log.log();
}];
$injector.invoke(myFunc);

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

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

最後要注意的是,你客戶端程式碼裡面的注入即使在 Angular 之外也是可用的。我們來看一個在 Angular 之外包裝的,透過注入呼叫 $log 服務的例子,點這裡。為什麼要把 ‘ng' 傳入方法的陣列?它是 Angular 的核心模組,當你包裝你的模組的時候是會被隱式添加的,但是如果你的指令要產生自己的注入實例的時候,你就必須明確添加了。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn