經過一番艱苦卓絕的鏖戰,我終於來到了控制器和作用域部分。控制器作為MVC的C,其重要性不可謂不重要;作用域決定了你可以拿到哪些東西,亦是分外重要。現在就來學習一下兩個東西。去看看$apply,$watch,$broadcast是個什麼鬼。 ...
經過一番艱苦卓絕的鏖戰,我終於來到了控制器和作用域部分。控制器作為MVC的C,其重要性不可謂不重要;作用域決定了你可以拿到哪些東西,亦是分外重要。現在就來學習一下兩個東西。去看看$apply,$watch,$broadcast是個什麼鬼。
一、談談MVC
阮一峰老師說Angular是一個叫MVVM的模式(http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html),而自由男人說這是一個MVC框架,個人認為都差不多,目標都是分層,便於協作和維護,這個跟我們的電腦網路的分層思想差不多(可以參看http://www.cnblogs.com/floor/p/6649424.html)。下麵還是按照MVC的觀點看看Angular。
ThinkPHP是一個服務端MVC框架,他的視圖就是我們前端的一切東西,控制器是從模型拿數據放到視圖,或者從視圖拿數據,交給模型,控制器是不直接與資料庫打交道的,與資料庫相關的操作就是模型的作用,我們在控制器調用M()方法就拿到了一個表對應的模型。
前端MVC則有不同,對Angular 而言,controller()方法構建的就是控制器,$scope上的東西就可以理解為模型,他們一般是調用後端介面拿到的,視圖就是你看到的東西。
二、單一控制器
這是最簡單的控制器應用形式,特點是控制器與視圖一一對應,無需考慮作用域之間的通信問題。缺點是隨著項目複雜度的增加可能變得難以維護。
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>single controller</title> </head> <body> <div ng-controller='dayCtrl'> <div> <h3>singleController</h3> </div> <h4>Today is {{day || "(不曉得)"}}</h4> </div> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",[]); myApp.controller('dayCtrl',function($scope){ var dayNames = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; $scope.day = dayNames[new Date().getDay()]; }) </script> </body> </html>
三、一個控制器管幾個作用域
自由男人給出了這樣一個圖
由此可見,將一個控制器用於多個沒有重合不部分的HTML相當於建立了多個控制器實例,他們對應多個作用域,控制器實例之間互不相干,作用域之間也互不相干。可以做個測試看看
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>use an controller more than once</title> </head> <body> <div ng-controller='testCtrl'> 我是一個域:<input type="text" name="" ng-model="data"> </div> <div ng-controller='testCtrl'> 我是另一個域:<input type="text" name="" ng-model="data"> </div> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",[]); myApp.controller('testCtrl',function($scope){ $scope.data="數據" }) </script> </body> </html>
結果是在任何一個文本框輸入都不會影響到另一個文本框,因為他們是相互隔離的。
四、作用域通信
上面講到將一個控制器用於幾個視圖會產生幾個隔離的作用域,但是有時候需要一部分數據能夠共用,此時就應該使用$rootScope了。
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>use an controller more than once</title> </head> <body> <div ng-controller='testCtrl'> 我是一個域:name:<input type="text" name="" ng-model="name"><br> sex:<input type="text" name="" ng-model="sex"> </div> <div ng-controller='testCtrl'> 我是一個域:name:<input type="text" name="" ng-model="name"><br> sex:<input type="text" name="" ng-model="sex"> </div> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",[]); myApp.controller('testCtrl',function($scope,$rootScope){ $scope.sex="男"; $scope.name = "大~熊"; $scope.$watch('sex',function(){ $rootScope.$broadcast("sexChange",$scope.sex); }); $scope.$on('sexChange',function(event,args){ $scope.sex = args; }) }) </script> </body> </html>
本想著做個gif展示一下的,發現ubuntu下做個gif有點麻煩,這個說明sex有倆個作用域共用,而name則是獨享的。$rootScope可以認為是一個頂層作用域,他能夠訪問到其他子域,本例中,通過監聽sex的變化,如果變化,則通過$rootScope發送一個sexChange事件,並將sex作為參數傳進去,然後在$scope上偵聽該事件,如果事件被觸發,則改變$scope.sex為傳進來的新值。
五、控制器的繼承
一個控制器的視圖包含另一個控制器,那麼裡面的控制器將繼承外面的控制器放到$scope上的屬性和方法。
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>繼承</title> </head> <body> <div ng-controller='fatherCtrl'> <div ng-controller="sonCtrl"> <h1>{{data}}</h1> </div> </div> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",[]); myApp.controller('fatherCtrl',function($scope,$rootScope){ $scope.data = "愚人節快樂!"; }) .controller("sonCtrl",function(){ }); </script> </body> </html>
sonCtrl中並沒有任何東西,但是它從fatherCtrl中繼承了data屬性(值為:愚人節快樂!);
六、關於顯示更新作用域
方法 | 幹啥的 |
$apply(expression) | 向作用域中應用變化 |
$watch(expression,hadler) | expression發生變化執行handler |
$watchCollection(object,handler) | object任一屬性變化則執行handler |
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset="UTF-8"> <title>updataScope</title> </head> <body> <div ng-controller='dayCtrl'> <h1>{{data}}</h1> </div> <script type="text/javascript" src="../node_modules/angular/angular.min.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp",[]); myApp.controller('dayCtrl',function($scope){ $scope.data = "愚人節快樂!"; setTimeout(function () { $scope.$apply(function () { $scope.data ="大家愚人節快樂!"; }); }, 1000); }) </script> </body> </html>
$watch()在上面的作用域通信已經用過了,$watchCollection()與之類似,關於這個$apply()我還不太清楚它有何作用。有知道的同學請指點一下。
先寫到這,過幾天繼續,要複習,要考試!