在上一節講完了關於應用開發中如數據綁定,加入樣式一類的基礎操做後,接下來,將在應用中,與控制其有關的一些事件。。。javascript
1、UI和控制器的分離html
咱們需要明白控制器在應用中的三個做用:java
【1】在應用模型中設置初始狀態express
【2】經過$scope對象向視圖(UI模版)暴露函數和模型數組
【3】監視模型發生變化的其它部分並作出對應的動做app
2、公佈scope中的數據模型ide
傳遞給控制器的$scope對象是一種用來向視圖暴露模型數據的機制。在咱們構建的應用中可能有其它數據,但是經過scope傳遞這些屬性時,angular僅僅考慮模型部分。函數
在以前的荔枝中,咱們經常看到$scope構建的數據實例,而這一過程是在控制器中完畢,在這裏,咱們也可以經過一些間接的方法從模版創建模型。性能
1.使用表達式:由於表達式在可它們關聯的控制器中運行,因此在表達式中設置屬性和控制器中設置屬性是一致的。即可以例如如下這麼作學習
<button ng-click='count=3'>Set count to three</button>
<div ng-controller='CountController'> <button ng-click='setCount()'>Set count to three</button> </div>
function CountController($scope) { $scope.setCount = function() { $scope.count=3; } }
3、用$watch觀察模型變化
$watch(watchFn, watchAction, deepWatch)該函數每個參數具體內容
watchFn:這個參數是angualr表達式字符串或返回監控模型的當前值的函數,該表達式會被運行屢次
watchAction:這是一個函數或者表達式,當watchFn變化時將調用他們,函數形式而言,它有watchFn的新舊值,及一個$scope引用,函數前面function(newValue,oldValue,scope)
deepWatch:這是一個可選的布爾參數,假設設置成true,angualr將監視對象每個屬性的變化
接下的栗子是以前購物車的升級版
<div ng-controller="CartController"> <div ng-repeat="item in items"> <span>{{item.title}}</span> <input ng-model="item.quantity"> <span>{{item.price | currency}}</span> <span>{{item.price * item.quantity | currency}}</span> </div> <div>Total: {{totalCart() | currency}}</div> <div>Discount: {{bill.discount | currency}}</div> <div>Subtotal: {{subtotal() | currency}}</div> </div>CartController:
function CartController($scope) { $scope.bill = {}; $scope.items = [ {title: 'Paint pots', quantity: 8, price: 3.95}, {title: 'Polka dots', quantity: 17, price: 12.95}, {title: 'Pebbles', quantity: 5, price: 6.95} ]; $scope.totalCart = function() { var total = 0; for (var i = 0, len = $scope.items.length; i < len; i++) { total = total + $scope.items[i].price * $scope.items[i].quantity; } return total; } $scope.subtotal = function() { return $scope.totalCart() - $scope.bill.discount; }; function calculateDiscount(newValue, oldValue, scope) { $scope.bill.discount = newValue > 100 ? 10 : 0; } $scope.$watch($scope.totalCart, calculateDiscount); }
上述結果
對於watch性能,咱們還需要注意一些潛在的性能問題
在上述樣例中,儘管其能夠正常的執行,但假設咱們在totoalCart()加一個調試的斷電,你將會看到它被調用了六次才渲染頁面,而在代碼中咱們很是easy跟蹤到三次,
1.模版中{{totalCart|currency}}
2.Subtotal()函數
3.$watch()函數
而angualr爲了驗證傳遞的模型變化已經全然傳遞,會再執行多一次,因此總共執行六次,而這樣的狀況很是easy形成一個循環依賴。因此咱們提供了下面的集中解決的方法
一種是在數組的每個元素上建立愛你$watch監控變化,不過這樣不過只計算了$scope屬性中的total,discount,subtotal
<div>Total: {{bill.total | currency}}</div> <div>Discount: {{bill.discount | currency}}</div> <div>Subtotal: {{bill.subtotal | currency}}</div>
function CartController($scope) { $scope.bill = {}; $scope.items = [ {title: 'Paint pots', quantity: 8, price: 3.95}, {title: 'Polka dots', quantity: 17, price: 12.95}, {title: 'Pebbles', quantity: 5, price: 6.95} ]; var calculateTotals = function() { var total = 0; for (var i = 0, len = $scope.items.length; i < len; i++) { total = total + $scope.items[i].price * $scope.items[i].quantity; } $scope.bill.totalCart = total; $scope.bill.discount = total > 100 ? 10 : 0; $scope.bill.subtotal = total - $scope.bill.discount; }; $scope.$watch('items', calculateTotals, true); }
而後由於咱們監視數組中的所有項,angualar不得不正確它進行一份拷貝用於對照,假設遇到一個具備很是多元素的列表時,可能會致使執行效率減小
因此咱們可以給$watch僅僅傳一個用於又一次計算屬性的watchFn
$scope.$watch(function() { var total = 0; for (var i = 0; i < $scope.items.length; i++) { total = total + $scope.items[i].price * $scope.items[i].quantity; } $scope.bill.totalCart = total; $scope.bill.discount = total > 100 ? 10 : 0; $scope.bill.subtotal = total - $scope.bill.discount; });
函數 | 定義 |
provider(name,object OR constructor()) | 可配置,有複雜邏輯的服務,可用於構造函數 |
factory(name,$getFunction()) | 不可配置,有複雜邏輯的服務,定義一個函數,調用時返回服務實例 |
service(name,constructor()) | 具備簡單邏輯,用於建立服務實例 |
在這裏,咱們利用以前討論過的items演示樣例使用factory()
// Create a module to support our shopping views var shoppingModule = angular.module('ShoppingModule', []); // Set up the service factory to create our Items interface to the // server-side database shoppingModule.factory('Items', function() { var items = {}; items.query = function() { // In real apps, we'd pull this data from the server... return [ {title: 'Paint pots', description: 'Pots full of paint', price: 3.95}, {title: 'Polka dots', description: 'Dots with polka’, price: 2.95}, {title: 'Pebbles', description: 'Just little rocks', price: 6.95} ]; }; return items; });
<html ng-app='ShoppingModule'> <body ng-controller="ShoppingController"> <h1>Shop!</h1> <table> <tr ng-repeat=」item in items」></tr> <td>{{item.title}}</td> <td>{{item.description}}</td> <td>{{item.price | currency}}</td> </tr> </table> </div>
5、用過濾器過濾數據
過濾器贊成你申明怎樣展現給用戶的數據轉換後插入到你的模版中。
{{ expression | filterName : parameter1 : ...parameterN }}
而angular有幾個自帶過濾器如:date,number,uppercase等,在這裏就很少介紹,主要咱們來學習假設本身建立一個本身定義過濾器
如下樣例是經過filter()函數構造一個名爲titleCase的過濾器,其做用是將句子中每個單詞的首字母大寫
var homeModule = angular.module('HomeModule', []); homeModule.filter('titleCase', function() { var titleCaseFilter = function(input) { var words = input.split(' '); for (var i = 0; i < words.length; i++) { words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1); } return words.join(' '); }; return titleCaseFilter; });
<body ng-app='HomeModule' ng-controller="HomeController"> <h1>{{pageHeading | titleCase}}</h1> </body>
function HomeController($scope) { $scope.pageHeading = 'behold the majesty of your page title'; }