AngularJS的双向数据绑定
例如代码:
<!doctype html>
<html ng-app>
<head>
<script src="angular-1.0.1.min.js"></script>
</head>
<body>
Your name:<input type="text" ng-model="yourname" placeholder="world"/>
<hr>
Hell0 {{yourname||'world'}}!
</body>
</html>
解析:
-
<html ng-app>
代表用AngularJS来处理整个HTML页面并引导应用 - 将文本输入指令input
<input ng-model="yourname"/>
绑定到your name 模型变量上 - 用双大括号标记将
yourname
添加到问候语文本 - 不需要为该应用注册一个事件或者事件处理程序
- 双向数据绑定:输入框的任何更改会立即反映到模型变量yourname(一个方向),模型变量的任何更改都会立刻反应到问候语文本(另一个方向)。
AngularJS映射模型—视图—控制器设计模式
模板(Templates)
模板是HTML和CSS编写的文件,展现应用的视图。AngularJS编译器是完全可扩展的,可以通过AngularJS在HTML中构建自己的HTML标记内容。
应用程序逻辑(Logic)和行为(Behavior)
应用程序逻辑和行为是用JavaScript定义的控制器。AngularJS与标准AJAX应用程序不同,不需要另外编写侦听器或DOM控制器,因为它们已经内置到AngularJS中了,使应用程序逻辑很容易编写、测试、维护和理解。
模型数据(Data)
模型是从AngularJS作用域对象的属性引申的。模型中的数据可能是Javascript对象、数组或基本类型,这都不重要,重要的是,他们都属于AngularJS作用域对象。
AngularJS通过作用域来保持数据模型与视图界面UI的双向同步。一旦模型状态发生改变,AngularJS会立即刷新反映在视图界面中,反之亦然
'$'前缀命名习惯
AngularJS内建服务,作用域方法,以及一些其他的AngularJS API都在名字面前使用一个‘$’前缀
但是不要用'$'来命名服务和模型,否则会产生名字冲突。
AngularJS链接与图片模板
使用ng-src指令来代替属性的src属性标签。也就是写成:<img ng-src="{{phone.imageURL}}">
如果用一个正常的src来绑定<img src="{{phone.imageUrl}}">
这样浏览器就会把AngularJS的{{表达式}}
标记直接进行字面解释,并且向一个非法的urlhttp://localhost:8000/app/{{phone.imageUrl}}
发起请求。因为浏览器载入页面时,同时也会请求载入图片,但是AngularJS会在页面载入完毕时才开始编译,也就是如果用正常的src来绑定<img>
浏览器请求载入图片时{{phone.imageUrl}}
还没有得到编译,会显示空白。
所以使用ng-src
指令来避免浏览器发死你个一个指向非法地址的请求,阻止 这一个现象。
多视图,路由和布局模板。
实现的内容:
增加了详细的信息视图,将index.html拓展为同时包含两个视图的模板代码,但是这样是很不方便的,所以我们要把index.html转化为“布局模板”,其他的局部模板根据当时的路由被填充进来,从而形成一个完整的视图展示出来。
AngularJS中的路由是通过$routeProvider来声明的,它是$route服务的提供者,使模板视图,控制器和url轻易集成起来。
依赖(服务)注入
依赖(服务)注入是AngularJS的核心,它的工作原理是:当应用引导时,AngularJS会创建一个注入器,这个注入器一开始并不知道$http和$route是做什么的,除非它已经在其他的模块被配置过,否则它跟本不知道这些服务的存在。
注入器的职责是载入指定的服务模块,并在这些注入模块中注册所有的服务提供者,并且当需要的时候给一个指定的函数注入依赖(服务),服务者懒惰加载依赖,也就是需要时才加载。
简单来讲就是先建立一个模块用来配置路由,配置路由的过程就是在这个模块当中通过config API 将$routeProvider注入到一个函数中,在函数中用$routeProvider.when来进行按需加载服务。
提供者是提供(创建)服务实例并且对外提供API接口的对象,它可以被用来控制一个服务的创建和运行时行为。对于$route服务来说,$routeProvider对外提供了API接口,通过API接口允许你为你的应用定义路由规则。
phoneCat这个例子中:
APP 模块变化:
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
这个APP模块是为了给应用配置路由,所以需要给应用配置了这个模块。
首先创建了一个名字叫phonecat的模块,这个名字与规定html中AngularJS应用范围时用的ng-app呼应,也就是ng-app的名字是phonecat,ng-app="phonecat";
其次应用config API将$routeProvider 注入规定函数当中,再用$routeProvider.when来按需加载,由url的映射段来规定AngularJS用哪个html视图模板和哪个js控制器。
index.html变化:
<html lang="en" ng-app="phonecat">
<html lang="en" ng-app="phonecat">
<head>
...
<script src="lib/angular/angular.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
$route服务通常和ngView指令一起使用。ngView指令的角色是为当前路由把对应的视图模板载入到布局模板中。
删除掉的代码现在被放置在phone-list.html模板中:
phone-list.html:
<div class="container-fluid">
<div class="row-fluid">
<div class="span2">
<!--Sidebar content-->
Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
<option value="name">Alphabetical</option>
<option value="age">Newest</option>
</select>
</div>
<div class="span10">
<!--Body content-->
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
<p>{{phone.snippet}}</p>
</li>
</ul>
</div>
</div>
</div>
控制器controller变化:
增加了PhoneDetailCtrl()控制器
function PhoneDetailCtrl($scope, $routeParams) {
$scope.phoneId = $routeParams.phoneId;
}
//PhoneDetailCtrl.$inject = ['$scope', '$routeParams'];
:phoneId参数的使用。$route服务使用路由声明/phones/:phoneId作为一个匹配当前URL的模板。所有以:符号声明的变量(此处变量为phones)都会被提取,然后存放在$routeParams对象中。
同时我们为手机详细信息视图添加一个占位模板。
phone-detail.htmlTBD: detail view for {{phoneId}}