angularjs入門學習【應用剖析中篇】

   在上一節講完了關於應用開發中如數據綁定,加入樣式一類的基礎操做後,接下來,將在應用中,與控制其有關的一些事件。。。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;
}
}

2.經過ng-model進行一個數據綁定


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

注意:在totalCart()創建一個監視,totalCart()用於計算該支付的總額,每當其發生變化時,watch函數就會調用calculateDiscount(),而後咱們設置對這個值適當的折扣。假設總值達昱100$,就設置折扣爲 10$,不然爲0;

上述結果



對於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);
}

注意:在$scope指定了一個字符串的items,items將做爲表達式在調用它的$scope做用域中運行

而後由於咱們監視數組中的所有項,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;
});

4、組織模塊的注入:


函數 定義
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 }}

當中expression爲隨意表達式,filterName爲你想用的過濾器的名稱,傳遞給過濾器的參數用冒號隔開,

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

相應的HTML模版

<body ng-app='HomeModule' ng-controller="HomeController">
<h1>{{pageHeading | titleCase}}</h1>
</body>

經過控制器賦值給模型變量

function HomeController($scope) {
$scope.pageHeading = 'behold the majesty of your page title';
}

執行結果例如如下圖

相關文章
相關標籤/搜索