欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

AngularJS深入探討scope,繼承結(jié)構(gòu),事件系統(tǒng)和生命周期

 更新時間:2016年11月02日 15:17:46   作者:kooky798  
這篇文章主要介紹了AngularJS的scope,繼承結(jié)構(gòu),事件系統(tǒng)和生命周期,較為詳細的分析了scope的作用域、層次結(jié)構(gòu)、繼承及生命周期相關(guān)概念與使用技巧,需要的朋友可以參考下

本文實例講述了AngularJS的scope,繼承結(jié)構(gòu),事件系統(tǒng)和生命周期。分享給大家供大家參考,具體如下:

深入探討 Scope 作用域

每一個 $scope 都是類 Scope 的一個實例。類 Scope 擁有可以控制 scope 生命周期的方法,提供事件傳播的能力,并支持模板渲染。

作用域的層次結(jié)構(gòu)

讓我們再來看看這個簡單的 HelloCtrl 的例子:

var HelloCtrl = function($scope){
  $scope.name = 'World';
}

HelloCtrl 看起來就跟普通的 JavaScript 構(gòu)造函數(shù)沒什么區(qū)別,事實上,除了 $scope 這個參數(shù)之外,確實沒什么新奇之處。不過,這個參數(shù)究竟是從哪里來的呢?

這個新的作用域是由 ng-controller指令使用 Scope.$new() 方法生成的。等一下,這么說來我們必須至少擁有一個 scope 的實例才能創(chuàng)建新的 scope!沒錯,AngularJS其實有一個 $rootScope(這個是所有其他作用域的父級)。這個 $rootScope 實例是在一個新的應用啟動的時候創(chuàng)建的。

ng-controller指令就是 可以創(chuàng)建作用域 指令的其中一個。AngularJS 會在任何它在DOM樹中碰到這種 可以創(chuàng)建作用域 指令的時候創(chuàng)建一個新的 Scope類的實例。這些新創(chuàng)建的作用域通過 $parent 屬性指向它自身的父作用域。DOM樹中會有很多 可以創(chuàng)建作用域 的指令,結(jié)果就是,很多作用域被創(chuàng)建了。

作用域的形式類似于父子、樹狀的關(guān)系,并且最根部的就是 $rootScope 實例。就像作用域是被DOM樹驅(qū)動著創(chuàng)建的一樣,作用域樹也是在模仿 DOM 的結(jié)構(gòu)。

現(xiàn)在你已經(jīng)知道了,一些指令會創(chuàng)建新的子級的作用域,你可能會想,為什么會需要這些復雜的東西。要想理解這一點,我們來演示一個例子,其中使用了 ng-repeat 循環(huán)指令。

控制器如下:

var WorldCtrl = function ($scope) {
  $scope.population = 7000;
  $scope.countries = [
    {name: 'France', population: 63.1},
    {name: 'United Kingdom', population: 61.8},
  ];
};

模版如下:

<ul ng-controller="WorldCtrl">
  <li ng-repeat="country in countries">
    {{country.name}} has population of {{country.population}}
  </li>
  <hr>
  World's population: {{population}} millions
</ul>

這個 ng-repeat 指令可以迭代一個 countries 的集合,并且為集合中的每一項都創(chuàng)建新的DOM 元素。ng-repeat 指令的語法非常容易理解;其中每一項都需要一個新的變量 country,并把它掛到 $scope 上面,以便視圖渲染使用。

但這里有一個問題,就是,每一個 country 都需要將一個新的變量掛載到一個 $scope 上去,而我們也不能就簡單的覆蓋掉前面被掛在上去的值。AngularJS 通過為集合中的每一個元素都創(chuàng)建一個新的作用域來解決這個問題。新創(chuàng)建的這些作用域跟相匹配的DOM樹結(jié)構(gòu)非常相像,我們也能通過之前提到的那個牛逼的 Chrome 擴展 Batarang 來可視化的看到這一點。

每一個作用域(以矩形標注邊界)維護屬于她自己的一段數(shù)據(jù)模型。給不同的作用域增加同名的變量是完全沒有問題的,不會發(fā)生命名沖突(不同的DOM元素會指向不同的作用域,并使用相對應的作用域的變量來渲染模板)。這樣一來,每個元素又有自己的命名空間,在前面的例子中,每一個<li> 元素都有自己的作用域,而 country 變量就定義在各自的作用域上面。

Scope的層次結(jié)構(gòu)和繼承

定義在作用于上的屬性對他的子級作用于來說是可見的,試想一下,子級作用域并不需要重復定義同名的屬性!這在實踐中是非常有用的,因為我們不必一遍又一遍的重復定義本來可以通過作用域鏈得到的那些屬性。

再來看看前面的例子,假設(shè)我們想要顯示給出的這些國家與世界總?cè)丝诘陌俜直取R獙崿F(xiàn)這個功能,我們可以在一個作用域上定義一個 worldsPercentage 的方法,并由 WorldCtrl 來管理,如下所以:

$scope.worldsPercentage = function (countryPopulation) { 
  return (countryPopulation / $scope.population)*100;
}

然后被 ng-repeat 創(chuàng)建的每一個作用域?qū)嵗紒碚{(diào)用這個方法,如下:

<li ng-repeat="country in countries">
  {{country.name}} has population of {{country.population}},
  {{worldsPercentage(country.population)}} % of the World's
  population
</li>

AngularJS中作用域的繼承規(guī)則跟 JavaScript 中原型的繼承規(guī)則是相同的(在需要讀取一個屬性的時候,會一直向繼承樹的上方查詢,直到找到了這個屬性為止)。

貫穿作用域鏈的繼承的風險

這種透過作用域?qū)哟侮P(guān)系的繼承,在讀數(shù)據(jù)的時候顯得非常的直觀、易于理解。但是在寫數(shù)據(jù)的時候,就變的有點復雜了。

讓我們來看看,如果我們在一個作用域上定義了一個變量,先不管是否在子級作用域上。JavaScript代碼如下:

var HelloCtrl = function ($scope) {
};

視圖的代碼如下:

<body ng-app ng-init="name='World'"> 
  <h1>Hello, {{name}}</h1>
  <div ng-controller="HelloCtrl">
    Say hello to: <input type="text" ng-model="name">
    <h2>Hello, {{name}}!</h2> 
  </div>
</body>

運行一下這段代碼,就可以發(fā)現(xiàn),這個 name 變量盡管僅僅是定義在了最頂級的作用域上,但在整個應用中都是可見的!這說明變量是從作用域鏈上繼承下來的。換句話說,變量是在父級作用域上定義的,然后在子級作用域中訪問的。

現(xiàn)在,我們一起來看看,如果在 <input> 中寫點字會發(fā)生什么,運行結(jié)果你可能會感到吃驚,因為 HelloCtrl 控制器所初始化的作用域創(chuàng)建了一個新的變量,而不是直接去修改$rootScope 實例中的值。不過當我們認識到作用域也只不過是在彼此間進行了原型繼承,也就不會覺得那么吃驚了。所有可以用在 JavaScript 對象上的原型繼承的規(guī)則,都可以同等的用在 作用域 的原型鏈繼承上去。畢竟 Scopes 作用域就是 JavaScript 對象嘛。

在子級作用域中去改變父級作用域上面的屬性有幾種方法。第一種,我們就直接通過 $parent 屬性來引用父級作用域,但我們要看到,這是一個非常不可靠的解決方案。麻煩之處就在于,ng-model 指令所使用的表達式非常嚴重的依賴于整個DOM結(jié)構(gòu)。比如就在 <input> 標簽上面的哪里插入另一個 可創(chuàng)建作用域 的指令,那$parent 就會指向一個完全不同的作用域了。

就經(jīng)驗來講,盡量避免使用 $parent 屬性,因為它強制的把 AngularJS 表達式和你的模板所創(chuàng)建的 DOM 結(jié)構(gòu)捆綁在了一起。這樣一來,HTML結(jié)構(gòu)的一個小小的改動,都可能會讓整個應用崩潰。

另一個解決方案就是,不要直接把屬性綁定到 作用域上,而是綁到一個對象上面,如下所示:

<body ng-app ng-init="thing = {name : 'World'}"> 
  <h1>Hello, {{thing.name}}</h1>
  <div ng-controller="HelloCtrl">
    Say hello to: <input type="text" ng-model="thing.name">
    <h2>Hello, {{thing.name}}!</h2> 
  </div>
</body>

這個方案會更可靠,因為他并沒有假設(shè) DOM 樹的結(jié)構(gòu)是什么樣子。

避免直接把數(shù)據(jù)綁定到 作用域的屬性上。應優(yōu)先選擇把數(shù)據(jù)雙向綁定到對象的屬性上(然后再把對象掛到 scope 上)。就經(jīng)驗而言,在給 ng-model 指令的表達式中,你應該有一個點(例如, ng-model="thing.name")。

作用域?qū)蛹壓褪录到y(tǒng)

層級關(guān)系中的作用域可以使用 event bus(一種事件系統(tǒng))。AngularJS可以在作用域?qū)蛹壷袀鞑ゾ呙难b備齊全的事件。事件可以從任何一個作用域中發(fā)出,然后向上($emit)和向下($broadcast)四處傳播。

AngularJS核心服務和指令使用這種事件巴士來發(fā)出一些應用程序狀態(tài)變化的重要事件。比如,我們可以監(jiān)聽$locationChangeSuccess 事件(由 $rootScope 實例發(fā)出),然后在任何 location(瀏覽器中就是URL)變化的時候都會得到通知,如下所示:

$scope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl){ 
  //react on the location change here
  //for example, update breadcrumbs based on the newUrl
});

每一個作用域?qū)ο蠖紩羞@個 $on 方法,可以用來注冊一個作用域事件的偵聽器。這個函數(shù)所扮演的偵聽器在被調(diào)用時會有一個 event 對象作為第一個參數(shù)。后面的參數(shù)會根據(jù)事件類型的不同與事件本身的配備一一對應。

類似于 DOM 事件,我們可以調(diào)用 event 對象的 preventDefault() 和 stopPropagation() 方法。stopPropagation() 方法將會阻止事件沿著作用域?qū)蛹壚^續(xù)冒泡,并且只在事件向上層傳播的時候($emit)才有效。

盡管 AngularJS 的事件系統(tǒng)是模仿了 DOM 的,但兩個事件傳播系統(tǒng)是完全獨立的,沒有任何共同之處。

雖然在作用域?qū)蛹壷袀鞑ナ录σ恍﹩栴}來說是一種非常優(yōu)雅方案(特別是對全局的,異步的狀態(tài)變化來說),但還是要適度使用。通常情況下,可以依靠雙向數(shù)據(jù)綁定來得到一個比較干凈的方案。在整個 AngularJS 框架中,一共只發(fā)出($emit)了三個事件($includeContentRequested,$includeContentLoaded,$viewContentLoaded)七個廣播($broadcast)($locationChangeStart, $locationChangeSuccess, $routeUpdate, $routeChangeStart,$routeChangeSuccess, $routeChangeError, $destroy)。正如你所看到的,作用域事件使用的非常少,我們應該在發(fā)送自定義的事件之前認真的評估一下其他的可選方案(多數(shù)會是雙向數(shù)據(jù)綁定)。

千萬不要在 AngularJS 中模仿 DOM 的基于事件的編程方式。大多數(shù)情況下,你的應用會有更好的架構(gòu)方式,你也可以在雙向數(shù)據(jù)綁定這條路上深入探索。

作用域的生命周期

作用域需要提供相互隔離的命名空間,避免變量的命名沖突。作用域們都很小,而且被以層級的方式組織起來,對內(nèi)存使用的管理來說很有幫助。當其中一個作用域不再需要 ,它就可以被銷毀了。結(jié)果就是,這個作用域所暴露出來的模型和方法就符合的垃圾回收的標準。

新的作用域通常是被 可創(chuàng)建作用域 的指令所生成和銷毀的。不過也可以使用 $new() 和 $destroy() 方法來手動的創(chuàng)建和銷毀作用域。

希望本文所述對大家AngularJS程序設(shè)計有所幫助。

  • 使用angularjs.foreach時return的問題解決

    使用angularjs.foreach時return的問題解決

    這篇文章主要介紹了使用angularjs.foreach時return的問題解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 詳解JavaScript的AngularJS框架中的作用域與數(shù)據(jù)綁定

    詳解JavaScript的AngularJS框架中的作用域與數(shù)據(jù)綁定

    這篇文章主要介紹了JavaScript的AngularJS框架中的作用域與數(shù)據(jù)綁定,包括作用域的繼承以及數(shù)據(jù)的單向和雙向綁定等重要知識點,需要的朋友可以參考下
    2016-03-03
  • AngularJs 延時器、計時器實例代碼

    AngularJs 延時器、計時器實例代碼

    這篇文章主要介紹了AngularJs 延時器、計時器實例代碼,需要的朋友可以參考下
    2017-09-09
  • Angular 多級路由實現(xiàn)登錄頁面跳轉(zhuǎn)(小白教程)

    Angular 多級路由實現(xiàn)登錄頁面跳轉(zhuǎn)(小白教程)

    這篇文章主要介紹了Angular 多級路由實現(xiàn)登錄頁面跳轉(zhuǎn)(小白教程),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • ng-repeat指令在迭代對象時的去重方法

    ng-repeat指令在迭代對象時的去重方法

    今天小編就為大家分享一篇ng-repeat指令在迭代對象時的去重方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • AngularJS對動態(tài)增加的DOM實現(xiàn)ng-keyup事件示例

    AngularJS對動態(tài)增加的DOM實現(xiàn)ng-keyup事件示例

    這篇文章主要介紹了AngularJS對動態(tài)增加的DOM實現(xiàn)ng-keyup事件示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • AngularJS包括詳解及示例代碼

    AngularJS包括詳解及示例代碼

    本文主要介紹AngularJS包括的基礎(chǔ)知識,這里整理了相關(guān)資料并附示例代碼和實現(xiàn)效果圖,有需要的小伙伴可以參考下
    2016-08-08
  • Angularjs的Controller間通信機制實例分析

    Angularjs的Controller間通信機制實例分析

    這篇文章主要介紹了Angularjs的Controller間通信機制,結(jié)合實例形式分析了Controller通信機制的原理、實現(xiàn)技巧與相關(guān)操作技巧,需要的朋友可以參考下
    2016-11-11
  • AngularJS ng-template寄宿方式用法分析

    AngularJS ng-template寄宿方式用法分析

    這篇文章主要介紹了AngularJS ng-template寄宿方式用法,結(jié)合實例形式分析了ng-template模板的相關(guān)使用技巧,需要的朋友可以參考下
    2016-11-11
  • 最新評論