修真院Web工程師零基礎全能課javascript
本節課內容html
AngularJs進階-做用域和控制器java
主講人介紹angularjs
沁修,葡萄藤技術總監數組
項目經驗豐富,擅長H5移動項目開發。瀏覽器
專一技術選型、底層開發、最佳代碼實踐規範總結與推廣。app
直播錄屏版框架
傳送門:https://v.qq.com/x/page/t0782...函數
文字解析版prototype
什麼是scope做用域?
scope做用域是一個指向應用model的對象object,也是表達式的執行環境。
做用域有層次結構,有根做用域,有不少子做用域,根據位置不一樣而不一樣。
做用域還能監控表達式,傳遞事件。
好比在html當中,咱們都會定義一個ng-app指令,那麼隨之而來就是一個做用域產生了。
不過由ng-app生成的做用域比較特殊,它是一個根做用域$rootscope,也就是其餘全部scope的頂層。
除此以外,還有不少指令都會產生一個做用域,好比ng-controller, ng-repeat等。這些做用域都擁有本身的繼承上下文,而且根做用域都是rootscope。
在咱們生成一個做用域以後,$scope對象就表明了這個做用域的數據。
咱們能夠在$scope內定義各類數據,以後能夠直接在html中以雙花括號的表達式的方式來讓html獲得這個變量。
scope的用法?
在正式開始接觸scope以前咱們再來熟悉一下js的全局變量和局部變量:
var foo = "foo";
function bar() {
var foo = "bar";
console.log(foo);
}
bar();
console.log(foo);
這裏說明,全局變量能夠在方法內引入,而局部變量只能在定義的方法內使用,angular做用域跟變量性質類似。
angularjs中的全局做用域:
var myApp = angular.module('myApp', []);
/*
*/
myApp.run(function($rootScope){
$rootScope.version = 2.0;
});
全局做用域是全部controller的scope的橋樑。
rootscope定義的值,能夠在各個controller中使用。
常常用於須要在多個頁面場景中的數據就能夠定義到全局做用域上。
angularjs中的局部做用域:
myApp.controller('homeCtrl', function($scope){
$scope.person = {
name: 'max'
}
})
myApp.controller('productCtrl',function($scope,$rootScope){
console.log($scope.person.name);//undefined
console.log($rootScope.version) //2.0
})
前面咱們已經說過,每個angular應用有且只有一個root scope,但能夠擁有多個child scope。
由於一些directive會建立新的child scope,當新的scope被建立後,他們將做爲一個child scope,加入到parent scope中。
這樣,建立了一個與它們附屬的DOM類似的樹結構。
當angular在html中對{{person}}求值時,它首先查看與當前元素關聯的scope的person屬性。
若是沒有找到對應的屬性,它將會一直向上搜索parent scope,直到到達root scope。
在javascript中,這個行爲被稱爲「原型繼承」,child scope典型地繼承自它們的parent。
$scope特色?
提供了$watch()方法,用於監聽模型的變化
提供了$apply()方法,用於傳播模型的變化
$watch()監聽模型變化,當模型發生變化,它會給你提示。
表達式:
$watch(watchExpression, listener, objectEquality);
watchExpression:監聽的對象,好比一個angular表達式如’scope.person’。
listener:當watchExpression變化時會被調用的函數或者表達式,它接收3個參數:
newValue(新值), oldValue(舊值), scope(做用域的引用)。
objectEquality:是否深度監聽,若是設置爲true,它告訴Angular檢查所監控的對象中每個屬性的變化.。
若是你但願監控數組的個別元素或者對象的屬性而不是一個普通的值, 那麼你應該使用它。
$scope.name = 'hello';
$scope.$watch('name',function(newValue, oldValue, scope){
console.log(newValue);
console.log(oldValue);
});
$timeout(function(){
$scope.name = "world";
},1000);
$apply()用於傳播模型的變化。
AngularJS 外部的控制器(DOM 事件、外部的回調函數如jQuery等)調用了AngularJS 函數以後,就須要調用$apply。
myApp.controller('homeCtrl', function($scope){
vm.name = 'hello';
setTimeout(function () {
vm.name = "world";
}, 2000);
})
預期的應該是先顯示hello, 兩秒後改成world。
但事實是咱們發現它不會自動變化,由於調研了外部的事件,因此須要用$apply方法就能夠了:
myApp.controller('homeCtrl', function($scope){
vm.name = 'hello';
setTimeout(function () {
$scope.$apply(function () {
vm.name = "world";
});
}, 2000);
})
$scope的生命週期?
建立 creation
↓
註冊監視器 watcher registration
↓
模型變化 model mutation
↓
變化檢測 mutation observation
↓
做用域銷燬 scope destruction
瀏覽器正常的事件流中,當瀏覽器接收到事件後,它會執行一個相應的javascript回調。
一旦回調函數執行完畢後,瀏覽器將會重繪DOM,並返回到繼續等待事件的狀態。
1.在應用啓動的過程當中,會建立rootscope,然後在模板的連接過程當中,一些directive會建立新的child scope。
2.directive在scope中註冊$watch,這些watch會用來向DOM傳播model的值。
3.更新模型狀態必須是在$apply方法中才能夠被觀察到,不過angular框架是封裝了這個方法過程的。
咱們一般無需擔憂,除非是以前提到過的,angular之外的一些方法事件在觸發後,不能正常調用$apply才須要手動去添加這個方法。
4.$apply方法結束後,angular會在根做用域執行一個$digest週期而且擴散到全部子做用域。
scope檢查全部$watch監聽的表達式,將如今的值與舊的值做比較。
這個過程會檢查模型狀態是否改變以及更新。
5.銷燬做用域,當不在須要子做用域的時候,就會被銷燬掉。
總結$scope?
一、提供了觀察者能夠監聽數據模型的變化
二、能夠將數據模型的變化通知給整個 App
三、能夠進行嵌套,隔離業務功能和數據
四、給表達式提供上下文執行環境
在scope以後咱們又來看看和它關係很是緊密的控制器controller。。。
什麼是控制器?
從做用上來說,controller主要是對視圖中的數據和事件函數進行掛載,同時處理一些業務的地方。
從功能上來說,在angularjs中,controller是一個js函數,用來擴展angular的子scope的實例。
所以它能夠用來設置scope對象的初始狀態,而且增長一些屬性行爲到scope中。
控制器使用?
在模板中聲明控制器
<div ng-controller="myController">...</div>
控制器實際上就是一個js的構造函數:
//控制器類定義
var myControllerClass = function($scope){
//模型屬性定義
$scope.text = "...";
//模型方法定義
$scope.do = function(){...};
};
//在模塊中註冊控制器
angular.module('someModule',[])
.controller("myController",myControllerClass);
控制器構造函數僅在AngularJS對HTML文檔進行編譯時被執行一次。
一旦控制器建立完畢,就意味着scope對象上的業務模型構造完畢,此後就再也不須要控制器了,由於scope對象接管了。
控制器和scope?
<html ng-app=「myApp">
<body ng-init=「foo={name:’hello'}」>
<div ng-controller=「myCtrl"></div>
</body>
</html>
對scope的影響是什麼樣的呢?
$rootScope: {
foo: {name: ‘hello'}
}
scope: {
prototype: $rootScope,
bar: ...
}
能夠看到ng-app指令建立了$rootScope對象,這個時候它仍是一個空對象。
body元素對應的scope對象仍是$rootScope,ng-init指令將foo對象掛到了$rootScope上
div元素又經過ng-controller指令建立了一個新的scope對象,這個對象的原型是$rootScope
由於繼承關係,若是在scope中引用foo會指向$rootScope.foo
注意不要在controller中作的事情:
1.DOM操做
2.表單輸入的格式化,用form controls
3.輸出內容的格式化和過濾,用filter
4.控制器之間的數據共享,另外定義services服務來處理
以上就是上節課的內容解析啦