AngularJS Phonecat (步骤8-步骤9)

导言


最近在学AngularJS的实例教程PhoneCat Tutorial App,发现网上的中文教程都比较久远,与英文版对应不上,而且缺少组件和文件重构两节。所以决定自己整理一个中文简明教程。

此篇为8-9节。

上一篇:AngularJS Phonecat (步骤6-步骤7)

8 模板链接和图片


在这一步,我们要为手机列表增加缩略图和链接。

数据

phones.json文件保存了手机id和手机图片的url,url指向app/img/phones/文件夹。

app/phones/phones.json (其中一组数据):

[
  {
    ...
    "id": "motorola-defy-with-motoblur",
    "imageUrl": "img/phones/motorola-defy-with-motoblur.0.jpg",
    "name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
    ...
  },
  ...
]

模板

app/phone-list/phone-list.template.html:

...

...
  • {{phone.id}}绑定到a标签的href属性,{{phone.name}}绑定到a标签。
  • 引入手机图片,需要设置img标签。如果直接使用src绑定{{phone.imageUrl}},Angular未初始化前就会展开绑定,也就会发出无效的url请求。为此,我们使用ngSrc命令,它会在Angular初始化后再进行绑定。

端到端测试

e2e-tests/scenarios.js:

...

it('should render phone specific links', function() {
  var query = element(by.model('$ctrl.query'));
  query.sendKeys('nexus');
//点击链接
  element.all(by.css('.phones li a')).first().click();
//检查链接的url是否正确
  expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s');
});

...

该测试验证程序是否能正确生成图片链接。在命令行输入npm run protractor运行测试。

9 路由与多视图


这一步,我们会学习如何创建布局模板,如何利用Angular路由模块(ngRoute)实现多视图。
当你在浏览器中输入/index.html。会重定向到/index.html#!/phones并显示手机列表。当点击手机链接时,会转到手机详情页面。

依赖

路由功能由ngRoute模块提供,这是一个独立于Angular核心框架的模块。

我们使用Bower来安装客户端依赖。更新bower.json配置文件来包含新的依赖关系:

bower.json:

{
  "name": "angular-phonecat",
  "description": "A starter project for AngularJS",
  "version": "0.0.0",
  "homepage": "https://github.com/angular/angular-phonecat",
  "license": "MIT",
  "private": true,
  "dependencies": {
    "angular": "1.5.x",
    "angular-mocks": "1.5.x",
    "angular-route": "1.5.x",
    "bootstrap": "3.3.x"
  }
}

指明"angular-route": "1.5.x",会让bower安装1.5.x版本的angular-route模块。

如果你是在全局环境中安装bower,你可以使用bower install进行安装。而这个项目我们已经预配使用npm来运行bower install,所以只需要输入命令行:

npm install

多视图、路由与布局模板

我们的程序逐渐增大,也变得更复杂。在上一节,我们只有一个的视图(用来显示手机列表),所有的模板代码都放置在phone-list.template.html中。这一节,我们会添加一个视图来展示手机详情。

为了添加详情页,我们会将index.html转换成布局模板(layout template),在所有页面中通用。其他局部模板(partial templates)会通过当前路由引入到布局模板中(当前路由决定引入哪个局部模板)。

Angular通过$routeProvider声明路由,它是$route服务的提供者。该服务会将控制器、视图模板、当前url连接起来。它还能实现深层链接:浏览器历史(后退/前进)、收藏标签。

ngRoute让控制器和特定url的模板关联起来。具体方法是:将组件关联到路由上,组件作为提供者负责提供视图模板和控制器。

关于依赖注入(DI):注入器(Injector)和提供者(Providers)

一般来说,一个对象只能通过三种方法来得到它的依赖项目:

  • 在对象内部创建依赖项目
  • 将依赖作为一个全局变量来进行查找或引用
  • 将依赖传递到需要它的地方
    第一种方法无法隔离对象和依赖项目,第二种方法则容易污染全局作用域。所以我们使用第三种方法,即依赖注入。依赖注入是一种设计模式,它移除了硬编码依赖,因此使得我们可以在运行中随时移除并改变依赖项目。这对于测试也很有好处,我们可以用测试环境中的一个模拟对象来替换生产环境中的一个真实对象。

依赖注入(DI)也是AngularJS的核心,所以我们要了解其基本原理。

1)Angular为什么需要依赖注入?
AngularJS的组件之间无法互相直接调用,一个组件必须通过注入器调用另一个组件。这样的好处是组件之间相互解耦,对象整个生命周期的管理都丢给了注入器。

2)Angular如何实现依赖注入?
程序启动时,Angular会创建一个注入器(injector),用于查找和注入程序所需的服务。注入器本身并不了解服务($http、$route)能做什么,甚至服务是否存在(除非服务配置在适当的模块定义中),它只是存放服务的容器。

注入器:

  • 加载依赖:加载程序依赖的模块定义
  • 注册依赖:注册模块定义的提供者
  • 注入依赖:当有实际的请求时,注入器通过提供者(注:提供者作为参数注入函数)实例化具体的服务及对应的依赖。

提供者(一般指组件):
提供者是提供(创建)服务实例的对象,它的配置API可用来控制服务的创建和运行的行为。比如$route服务,$routeProvider暴露的API允许你为程序定义路由。

注意:提供者只能注入到config函数,因此你不能把$routeProvider注入PhoneListController

Angular模板解决了全局变量的问题。与AMD或者require.js模块不同,Angular模板不需处理脚本加载顺序和延迟获取等问题,这些目标是独立的模块系统,他们可以并列存在和实现自己的目标。

要深入理解Angular的依赖注入,请参阅Understanding Dependency Injection

模板

$route服务通常与ngView指令联合使用。ngView指令会将当前路由的视图模板加到布局模板中,这让index.html模板看起来更简洁。

app/index.html:


  ...
  
  
  
  
  ...
  
  



  

我们在index.html中增加了4个新的

你可能感兴趣的:(AngularJS Phonecat (步骤8-步骤9))