angular应用骨架
ng-app定义的 位置,决定了angular的处理边界。
可以绑定在<html>、<body>
或者任意的<div>
标签上
MVC Model View Controlle
- 用来容纳数据的模型,代表当前的状态。
- 用来展示数据的视图
- 用来管理模型和视图之间关系的控制器
- 正确定义控制器:定义成模型的一部分
<html ng-app='myAPP'> |
var myAppModel = angular.module('myApp',[]); |
上面的代码中,myApp代表html中模型的名称,通过调用Angular的.module方法,创建新的模型,并将控制器定义给模型。
模板和数据绑定 介绍基本元素
- 控制器中所有定义在$scope
中的数据,都可以在模型中使用(上面代码中,的部分会显示
sisi
)
- 模型中通过指令ng-module=''
进行数据绑定元素绑定到模型属性上。
显示文本
- 双花括号的方式
<p></p>
- 基于属性的指令
<p ng-bind="greeting"></p>
,这条语句会绑定到上面的输入(假设有的话。)
- 双花括号的方式
表单输入
<form ng-submit="requestFunding()" ng-controller="StartUpController">
Starting: <input ng-change="computeNeeded()" ng-model="startingEstimate">
Recommendation:{{needed}}
<button>Fund my startup!</button>
<button ng-click="reset()">Reset</button>
</form>function StartUpController($scope){
$scope.computeNeeded=function(){
$scope.need=$scope.startingEstimate*10;
};
$scope.requestFuning = function(){
windown.alert("Sorry,please get more customers first.");
};
$scope.reset = function(){
$scope.startingEstimate = 0;
};
}上面的代码实现下面的功能:
- 监视输入框,当检测到数据变化时计算推荐值
- 点击reset按钮后,重置数值。
列表、表格&其他迭代型元素
ng-repeat
根据集合中的项目创建一组元素的多分拷贝<table ng-controller = 'AlbumController'>
<tr ng-repeat = 'track in album'>
<td>{{$index+1}}</td>
<td>{{track.name}}</td>
<td>{{track.duration}}</td>
</tr>
</table>
表达式
区分UI和控制器的职责
控制器职责
- 为应用中的模型设置初始状态
- 通过
$scope
对象把数据模型和函数暴露给视图(UI模板) - 监视模型其余部分的变化,采取相应的动作
$scope
暴露模型数据- 显式的:
$scopt.count=5
- 隐式的:表达式
ng-click="count = 5"
/ 指令ng-model
- 显式的:
$watch
监控数据模型的变化函数定义为
$watch(watchFn,watchAction,deepWatch)
watchFn
可以是表达式或者函数的字符串,返回被监控的数据模型的当前值。
watchAction
可以是表达式或者函数,当watchFn
发生变化时会被调用,接收三个参数,函数签 名如:function(newValue,oldValue,scope)
。
deepWatch
布尔值,当为true
时,将监控数组的所有元素或者对象上的每一个属性。$watch()
的性能问题<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>
<button ng-click="remove($index)">Remove</button>
</div>
<div>Total:{{totalCart()|currency}}</div>
<div>Discount:{{discount|currency}}</div>
<div>Subtotal:{{subtotal()|currency}}</div>$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.discount;
}
function calculateDiscount(newV,oldV,scope){
$scope.discount = newV > 100 ? 10:0;
}
$scope.$watch($scope.totalCart,calculateDiscount);上面的代码实现的功能:当总金额超过100时,给予10$的折扣。
虽然功能可以实现,但是在实际运行中过多的调用了
totalCart()
函数,这不是良好的代码。有多种方法解决上述问题,其中一种是监控
items
数组$scope.bill={};
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);
<!--对应的模型中的元素要变为-->
<div>Total:{{bill.totalCart|currency}}</div>
<div>Discount:{{bill.discount|currency}}</div>
<div>Subtotal:{{bill.subtotal|currency}}</div>这种策略可能会工作的很好,但是angular会制作一份数组的拷贝(为了监控其变化)。这对于大型数组来说就会很耗费资源,如果只需要重新计算 bill属性就会好很多。如下:
$scope.bill={};
$scope.$watch(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('things.a+things.b',callMe(...));
- 放到数组或对象中,
deepWatch
设置为true
$scope.watch('things',callMe(...),true);
使用Module 组织依赖关系
先看一个例子
function ItemsViewController( $scope){ |
潜在问题:
- Items
不可复用
- 控制器边界难以界定,
- 不利于单元测试(启动服务器/monkey patching)
接下来是模块和模块注入功能
function ShoppingController($scope,Items){ |
- 关于创建服务
provider(name,object or constructor() ) | 一个可配置服务,若传递Object作为参数,则该对象必须带有一个$get 函数,该函数需要返回服务的名称。否则,默认传递的是构造函数。 |
---|---|
factory(name,$get Function() ) | 不可配置服务,需要指定一个函数,当调用函数时返回服务的实例。 |
service(name,constructor) | 不可配置服务,与provider类似。 |
使用过滤器格式化数据
语法
{{ express | filterName : parameter1 : ... parameterN }} |
- 内置过滤器: ` currtency,date,number,uppercase`等。 比如:` {{12.9 | currency | number:0 }}` 会显示成`$13`
- 自定义过滤器:eg.首字母大写
|
然后就可以愉快的使用他们了:
<h1>{{pageHeading | titleCase}}</h1> |
路由和$location
作用 :对于浏览器所指向的特定URL,Angular 会加载并显示一个模板,并实例化一个控制器来为模板提供内容。
创建 :调用$routeProvider
服务上的函数来创建路由,把需要创建的路由当成一个配置块传给这些函数即可。eg:
var someModule = angular.module('someModule',[.....dependencies...]); |
与服务器交互
$http 服务
function ShoppingController($scope, $http) { |
指令修改DOM
创建指令,就像创建服务一样: 通过模块对象的API来定义,只需要调用directive()函数即可。
var appModule = angular.module('appModule',[]); |
实际的小例子
var appModule = angular.module('app', []); |
使用新定义的指令,则视图显示时,该按钮会处于聚焦状态
<button ngbk-focus ng-click="clickUnfocused()"> |
校验用户输入
示例如下:
<form name='addUserForm' ng-controller="AddUserController"> |
function AddUserController($scope) { |
以上所有的验证工作均可在模板内完成,而不需要控制器进行监视。