在对AngularJS进行简单了解的基础上学习Phonecat实例,可以分为环境搭建与运行、关键知识点解析、总结三个部分。
1. 环境搭建与运行
1.1 下载angular-phonecat
使用git clone 代码:
git clone https://github.com/angular/angular-phonecat.git
注意:如果在这里添加 --depth 的话,会使之后的checkout出现问题。
1.2 安装所需工具
运行以下代码安装所需工具:
npm install
1.3 分步骤学习
按照reademe.md使用checkout进行切换:
git checkout step-?
- git checkout step-0 引导应用程序
- git checkout step-1 静态模板程序
- git checkout step-2 动态MVC程序
- git checkout step-3 动态MVC程序+组件
- git checkout step-4 动态MVC程序+组件+重新构建文件和目录
- git checkout step-5 过滤器
- git checkout step-6 双向数据绑定
- git checkout step-7 XHR和依赖注入
- git checkout step-8 添加模板链接和图像
- git checkout step-9 添加路由和多视图
- git checkout step-10 实现详情页
- git checkout step-11 自定义过滤器
- git checkout step-12 详情页图片点击与显示事件处理
- git checkout step-13 REST和自定义服务
- git checkout step-14 添加动画
1.4 启动angular-phonecat
输入以下代码启动angular-phonecat:
npm start
如果此时控制台显示如下图,则原因是端口8000被占用,禁用端口即可。
如果控制台显示如下图,则启动成功,在浏览器中输入http://localhost:8000(http://127.0.0.1:8000 | http://youIP:8000)即可进行访问。
1.5 测试angular-phonecat
输入以下代码进行测试:
npm test
这里需要注意的是,angular-phonecat测试的浏览器是chrome和firefox,可以根据自己的需要在angular-phonecat/e2e-tests/protractor.conf.js中进行修改。
2. 关键知识点解析
2.1 ng-app指令
ng-app指令标记了AngularJS脚本的作用域,在<html>中添加ng-app属性即说明整个<html>都是AngularJS脚本作用域。开发者也可以在局部使用ng-app指令,如<div ng-app>,则AngularJS脚本仅在该<div>中运行。
2.2 {{}}表达式
AngularJS表达式Angular expression是一种类似于JavaScript的代码片段,AngularJS表达式仅在AngularJS的作用域中运行,而不是在整个DOM中运行。
AngularJS会将{{}}中的表达式运算结果插入DOM中,DOM也会随着表达式运算结果的改变而实时更新。
2.3 控制器
AngularJS 应用程序被控制器控制。
ng-controller 指令定义了应用程序控制器。
ng-model 指令绑定输入域到控制器的属性。
控制器是 JavaScript 对象,由标准的 JavaScript 对象的构造函数创建。
2.4 迭代器
ng-repeat 指令对于集合中(数组中)的每个项会 克隆一次 HTML 元素。
如在本实例中,<li>标签里面的ng-repeat="phone in phones"语句是一个AngularJS迭代器。这个迭代器告诉AngularJS用第一个<li>标签作为模板为列表中的每一部手机创建一个<li>元素。
2.5 filter过滤器
过滤器可以通过一个管道字符(|)和一个过滤器添加到表达式中,过滤器一般有以下几种:
- uppercase 过滤器:将字符串格式化为大写
- lowercase 过滤器:将字符串格式化为小写
- currency 过滤器:将数字格式化为货币格式
- orderBy 过滤器:根据表达式排列数组
- filter 过滤器:从数组中选择一个子集
- 自定义过滤器:使用app.filter('newname', function() { });
2.6 双向数据绑定
在本实例中,step-6使用AngularJS在select元素和orderProp模型之间创建了一个双向数据绑定,orderProp会被用作orderBy过滤器的输入。
实现步骤为:
- 增加了一个叫做orderProp的<select>标签(这样用户就可以选择提供的两种排序方法)。
- 在filter过滤器后面添加一个orderBy过滤器用其来处理进入迭代器的数据。
- orderBy过滤器以一个数组作为输入,复制一份副本,然后把副本重排序再输出到迭代器。
2.7 XHR和依赖注入
XHR是XMLHttpRequest 的简称,XMLHttpRequest 用于在后台与服务器交换数据,主要是为了实现在不重新加载整个网页的情况下,对网页的某部分进行更新。简单说,浏览器中URL不变,但页面中局部元素有改变。
XHR有两个方法open(method,url,async)和send(string);
AJAX 指的是异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。
XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true,所以可以看得出来AJAX是XHR中的一种,只不过是异步加载数据。
XHR有两个方法open(method,url,async)和send(string);
AJAX 指的是异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。
XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true,所以可以看得出来AJAX是XHR中的一种,只不过是异步加载数据。
依赖注入(Dependency Injection)即控制反转(Inversion of Control),是软件工程领域的一种设计模式,主要用来解决代码的耦合问题,也是轻量级的Spring框架的核心。
简单说就是一段代码想共用,不想手工插入到指定位置,想注入进去,这里就可以使用DI(Dependency Injection).
其实现方式如下:
- 方式1 (基于接口): 可服务的对象需要实现一个专门的接口,该接口提供了一个对象,可以从用这个对象查找依赖(其它服务)。早期的容器Excalibur使用这种模式。
- 方式2 (基于setter): 通过JavaBean的属性(setter方法)为可服务对象指定服务。HiveMind和Spring采用这种方式。
- 方式3 (基于构造函数): 通过构造函数的参数为可服务对象指定服务。PicoContainer只使用这种方式。HiveMind和Spring也使用这种方式。
在本实例中,$http向Web服务器发起一个HTTP GET请求,索取phone/phones.json(注意,url是相对于我们的index.html文件的)。服务器用json文件中的数据作为响应。(这个响应或许是实时从后端服务器动态产生的。但是对于浏览器来说,它们看起来都是一样的。为了简单起见,教程里面简单地使用了一个json文件。)
$http服务用success返回[对象应答][ng.$q]。当异步响应到达时,用这个对象应答函数来处理服务器响应的数据,并且把数据赋值给作用域的phones数据模型。注意到AngularJS会自动检测到这个json应答,并且已经为我们解析出来了!
$http服务用success返回[对象应答][ng.$q]。当异步响应到达时,用这个对象应答函数来处理服务器响应的数据,并且把数据赋值给作用域的phones数据模型。注意到AngularJS会自动检测到这个json应答,并且已经为我们解析出来了!
2.8 ng-src
如果我们仅仅用一个正常src属性来进行绑定(<img class="diagram" src="{{phone.imageUrl}}">),浏览器会把AngularJS的{{ 表达式 }}标记直接进行字面解释,并且发起一个向非法urlhttp://localhost:8000/app/{{phone.imageUrl}}的请求。因为浏览器载入页面时,同时也会请求载入图片,AngularJS在页面载入完毕时才开始编译——浏览器请求载入图片时{{phone.imageUrl}}还没得到编译!有了这个ngSrc指令会避免产生这种情况,使用ngSrc指令防止浏览器产生一个指向非法地址的请求。
src和ng-src的写法对比如下:
<img src="http://www.gravatar.com/avatar/{{hash}}"/>
<img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
为什么要使用ng-src呢?官方的解释是:
The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}.
(浏览器将{{hash}}里的值,也即src属性值替换成文本以后可能就停止干活了。)
src和ng-src的写法对比如下:
<img src="http://www.gravatar.com/avatar/{{hash}}"/>
<img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
为什么要使用ng-src呢?官方的解释是:
The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}.
(浏览器将{{hash}}里的值,也即src属性值替换成文本以后可能就停止干活了。)
3. 总结
3.1 引导Angular应用程序
通过ngApp指令来自动引导AngularJS应用是一种简洁的方式,适合大多数情况。在高级开发中,例如使用脚本装载应用,您也可以使用bootstrap手动引导AngularJS应用。
AngularJS应用引导过程有3个重要点:
AngularJS应用引导过程有3个重要点:
- 注入器(injector)将用于创建此应用程序的依赖注入(dependency injection);
- 注入器将会创建根作用域作为我们应用模型的范围;
- AngularJS将会链接根作用域中的DOM,从用ngApp标记的HTML标签开始,逐步处理DOM中指令和绑定。
一旦AngularJS应用引导完毕,它将继续侦听浏览器的HTML触发事件,如鼠标点击事件、按键事件、HTTP传入响应等改变DOM模型的事件。这类事件一旦发生,AngularJS将会自动检测变化,并作出相应的处理及更新。
未完待续......
3.2 AngularJS的MVC
这里需要注意的是:
- 一个作用域(scope)可以视作模板、模型和控制器协同工作的粘接器。
- 模型和视图相互作用、相互影响就是作用域(scope)在起作用,它保证了两者的同步。
3.3 AngularJS的MVC中使用组件和过滤器
这里需要注意的是:
- 数据绑定是AngularJS的一个核心特性。当页面加载的时候,AngularJS会根据输入框的属性值名字,将其与数据模型中相同名字的变量绑定在一起,以确保两者的同步性。
- 用户在输入框中输入的数据名字称作query,会立刻作为列表迭代器(phone in phones | filter:query`)其过滤器的输入。当数据模型引起迭代器输入变化的时候,迭代器可以高效得更新DOM将数据模型最新的状态反映出来。
- ngRepeat会根据filter过滤器生成的手机记录数据数组来自动更新视图。整个过程对于开发者来说都是透明的。
3.4 AngularJS中的XHR和依赖注入
上图所示的三个步骤分别为:
- 依赖注入识别$xhr服务依赖PhonelistCtrl控制器。
- 使用DI(依赖注入)检查$xhr服务是否已经实例化,如果没有那就从Service Factory Repository使用工厂函数构造它。
- DI(依赖注入)提供实例化后的$xhr服务给PhonelistCtrl控制器。
angularjs中使用$http来发出请求,接受返回过来的数据.主要支持以下几种方法:
- $http.get
- $http.head
- $http.post
- $http.put
- $http.delete
- $http.jsonp
- $http.get('/someUrl').success(successCallback);
需要注意的是:
- get 请求的是本站的服务器,不能直接拷贝到本地运行,会存在跨域问题。
- 当控制器构造的时候,AngularJS的依赖注入器会将这些服务注入到你的控制器中。当然,依赖注入器也会处理所需服务可能存在的任何传递性依赖(一个服务通常会依赖于其他的服务)。
- 参数名字非常重要,因为注入器会用他们去寻找相应的依赖。
未完待续......