在这一步中,您将学到如何创建一个布局模板,并且学习怎样使用一个叫做ngRoute的Angular模块来构建一个具有多重视图的应用。

  ·当您现在访问/index.html,您将被重定向到/index.html#!/phones,电话列表会显示在浏览器中;

  ·当您点击一部电话的超链接,URL会改变至该指定电话,浏览器将展示一个简短的电话细节页面。

最大的不同列举如下,您可以点击这里在GitHub上查看全部的不同。

依赖

这一步中添加的路由功能是由Angular中的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去安装一个与Angular1.5.x版本兼容的angular-route模块版本。我们必须告诉bower去下载和安装这些依赖。

npm install

多重视图,路由和布局模板

我们的应用正在逐步变得复杂。在这一步之前,应用为我们的用户提供了一个单页视图(包括电话列表),并且所有的模板代码都位于phone-list.template.html文件下。构建应用的下一步,是添加一个能展示我们列表中每一部电话的细节的视图。

为了添加细节视图,我们将index.html转换成一个我们称之为“布局模板”的模板,一个于我们应用中所有视图都公共的模板。其他被包含在该布局模板中的“局部模板”依赖于当前的“路由”--当前展示给用户的视图。

Angular应用间的路由通过$routeProvider声明,这被$route服务所提供。该服务使得将控制器,视图模板和当前浏览器的URL捆绑起来变得容易。使用这点特性,我们可以实现深度链接,这使得我们可以充分利用浏览器的历史记录(前进和后退的导航)以及电子书签。

关于依赖注入,注入器和提供者的笔记

正如你注意到的,依赖注入在Angular中处于核心地位,所以对你来说深入了解它是很重要的。

在引导应用时,Angular创建一个注入器,这被用于找到和注入您应用中需要被用到的服务。注入器本身并不知道$http或$route这些服务做了什么。事实上,注入器甚至不知道这些服务的存在,除非它被适当的模块定义所配置。

注入器只执行了下面的步骤:
  ·加载您在应用中指定的模块定义;

  ·注册这些模块定义中定义的所有提供者;

  ·一旦被要求这么做,通过提供者,这作为可注入的函数中的参数,来懒惰式(lazily,需要时才加载)实例化服务和他们的依赖。

提供者是用来提供(创建)服务实例和对外配置API的对象,这可以被用来控制一个服务创建和运行时的行为。对于$route服务来说,$routeProvider提供API来允许您定义您应用中的路由。

(注意:提供者仅仅能被注入config函数,因此您不能在运行时将$routeProvider注入PhoneListController。)

Angular模块解决了从应用中移除全局变量的问题并且提供了配置注入器的方法。与AMD或require.js模块不同的是,Angular模块不会去试图解决脚本加载顺序或懒惰式脚本获取的问题。这些目标是完全独立的,并且每一个模块系统能并肩运作来实现他们的目标。

为了深入您对Angular依赖注入的理解,请看这里。

模板

$route服务经常和ngView指令结合使用。ngView指令扮演的角色是将当前路由的视图模板包含进布局模板。这使得其和我们的index.html完美契合。

app/index.html:

<head>
...
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="app.module.js"></script>
<script src="app.config.js"></script>
...
<script src="phone-detail/phone-detail.module.js"></script>
<script src="phone-detail/phone-detail.component.js"></script>
</head>
<body> <div ng-view></div> </body>

我们添加了4个额外的<script>标签来在我们的应用中加载额外的JavaScript文件:
  ·angular-route.js:定义了Angular的ngRoute模块,这为我们提供路由;

  ·app.config.js:为我们的主模块配置提供者(参见下文);

  ·phone-detail.module.js:定义了一个包含phoneDetail组件的新模块;

  ·phone-detail.component.js:定义了一个phoneDetail组件的模型(参见下文)。

注意到我们在index.html模板中移除了<phone-list></phone-list>一行并且用一个包含ng-view属性的div来替换它。

配置一个模块

模块的.config()方法为我们提供了获取用于配置的提供者的入口。为了在我们的应用中获取定义于ngRoute的提供者,服务和指令,我们需要在我们的phonecatApp模块中将ngRoute添加为一个依赖。

app/app.module.js:

angular.module('phonecatApp', [
'ngRoute',
...
]);

现在,除了核心的服务和指令,我们也能为我们的应用配置$route服务(使用其提供者)。为了能迅速定位配置代码,我们将其列为一个单独的文件并且添加.config后缀。

app/app.config.js:

angular.
module('phonecatApp').
config(['$locationProvider', '$routeProvider',
function config($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!'); $routeProvider.
when('/phones', {
template: '<phone-list></phone-list>'
}).
when('/phones/:phoneId', {
template: '<phone-detail></phone-detail>'
}).
otherwise('/phones');
}
]);

通过使用.config()方法,我们请求将必要的提供者( 比如$routeProvider)注入到我们的配置函数,然后使用它们的方法来制定对应服务的行为。在这里,我们使用$routeProvider.when()$routeProvider.otherwise()方法来指定我们的应用路由。

我们的路由定义如下:

  ·when('/phones'):决定将被展示的视图,当URL的哈希片段为/phones。通过指定的模板,Angular会创建一个phoneList组件的实例来管理视图。注意到这和我们在index.html使用的是相同的标记。

  ·when('/phones/:phoneId'):决定将被展示的视图,当URL的哈希片段为/phones/<phoneId>, <phoneId>是URL中变化的部分。管理phoneDetail组件中的视图。

  ·otherwise('/phones'):定义一个指向的回退路由,当没有被定义的路由于当前URL匹配。(这里会指向/phones)。

我们复用了我们已经构建的phoneList组件和一个新的“模型”phoneDetail组件。到目前为止,phoneDetail组件仅仅会展示选中电话的ID。(不是那么令人印象深刻,我们会在下一步中扩展它)。

注意到:phoneId作为路由声明的第二个参数,$route服务使用路由声明--'/phones/:phoneId'--作为一个与当前URL相匹配的模板。所有用:前缀定义的变量都被提取进入了$routeParams对象。

phoneDetail组件

我们创建了一个phoneDetail组件来处理电话细节视图。我们遵循和phoneList一样的惯例:使用一个独立的模块来创建phoneDetail模块,这在我们的phonecatApp模块中被添加为依赖。

app/phone-detail/phone-detail.module.js:

angular.module('phoneDetail', [
'ngRoute'
]);

app/phone-detail/phone-detail.component.js:

angular.
module('phoneDetail').
component('phoneDetail', {
template: 'TBD: Detail view for <span>{{$ctrl.phoneId}}</span>',
controller: ['$routeParams',
function PhoneDetailController($routeParams) {
this.phoneId = $routeParams.phoneId;
}
]
});

app/app.module.js:

angular.module('phonecatApp', [
...
'phoneDetail',
...
]);

一点关于子模块依赖的笔记

phoneDetail模块依赖于ngRoute模块,以此来提供$routeParams对象,这被用于phoneDetail组件的控制器中。由于ngRoute也是主模块phonecatApp中的依赖,其服务和指令在整个应用中都是可获取的(包括phoneDetail组件)。

这意味着及时我们不为phoneDetail组件的依赖列表中引入ngRoute,我们的应用依然可以正常工作。虽然删除子模块中哪些已经在主模块中引入的依赖听上去还不错,但这却损害了我们来之不易的模块化。

此处的额外知识是:

  ·永远清楚描述一个子模块的所有依赖。不要依赖于任何继承于父模块的依赖。(因为父模块可能哪天就不见了。)

总结

随着路由的建立和电话列表视图的实现,让我们进入下一步来实现一个正确的电话细节列表。

[Angular Tutorial] 9 -Routing & Multiple Views的更多相关文章

  1. Routing(路由) & Multiple Views(多个视图) step 7

    Routing(路由) & Multiple Views(多个视图) step 7 1.切换分支到step7,并启动项目 git checkout step-7 npm start 2.需求: ...

  2. [Angular Tutorial]PhoneCat Tutorial App

    (注:曾经在<不敢止步>一书中看到学到一个观点,作者认为学习一门技术最好的方法就是翻译某部领域书籍.这里我决定做一次尝试,接下来花1个月左右时间,将Angular Tutorial Pho ...

  3. AngularJS学习---Routing(路由) & Multiple Views(多个视图) step 7

    1.切换分支到step7,并启动项目 git checkout step- npm start 2.需求: 在步骤7之前,应用只给我们的用户提供了一个简单的界面(一张所有手机的列表),并且所有的模板代 ...

  4. [Angular Tutorial] 3-Components

    在先前的步骤中,我们看到了一个控制器和一个模板如何一起工作来将一个静态的HTML文件转化为动态页面(view).一般说来,这在单页应用中一种非常常见的模式(在Angular应用中尤其是这样): ·客户 ...

  5. [Angular Tutorial] 7-XHRs & Dependency Injection

    我们受够了在应用中用硬编码的方法嵌入三部电话!现在让我们用Angular内建的叫做$http的服务来从我们的服务器获取更大的数据集吧.我们将会使用Angular的依赖注入来为PhoneListCtrl ...

  6. [Angular Tutorial] 0-Bootstraping

    在这一节的tutorial中,您将会逐渐熟悉AngularJS phonecat app的最重要的源代码文件.您也将学到如何将开发服务器与angular-seed绑定到一起,并且在浏览器中运行应用. ...

  7. angular 2 - 004 routing 路由

    https://angular.io/tutorial/toh-pt5 定义一个模块用来定义路由 src/app/app-routing.module.ts import { NgModule } f ...

  8. [Angular 2] Pipes with Multiple Parameters

    Showing how to set up a Pipe that takes multiple updating inputs for multiple Component sources. imp ...

  9. [Angular Tutorial] 14 -Animations

    在这一步中,我们将会通过在我们先前创建的模板代码中添加CSS和JavaScript动画效果来扩展我们的web应用. ·我们现在使用ngAnimate模块来允许动画效果贯穿整个应用. ·我们也依赖于自带 ...

随机推荐

  1. 我终于有案例库啦(github 提供的)

    穷逼一个,一直在纠结要不要买个服务器什么的. 后来在慕课网看 git 教程时看到 github 可以帮你展示网页哟,于是我便有了这个案例库. 网址:https://foreverz133.github ...

  2. linux 命令实现原理

    我们知道有些Linux的命令涉及到一些高效率的算法,在此做出一个积累吧,不是系统的. 1.tail命令打印一个文件的最后num行 2.grep命令从文本中匹配字符串 基于正则表达式的匹配很快. it ...

  3. opencart配置United States Postal Service快递

    1.安装United States Postal Service 2.登录https://registration.shippingapis.com/,注册帐号,稍后会收到邮件 3.打开邮件,记下Us ...

  4. Nginx代理外网映射

    外网映射内网端口8080, 外网访问使用端口8379: nginx监听8080和80端口 #user nobody; worker_processes ; #error_log logs/error. ...

  5. 无法加载shockwave flash

    热心网友 360浏览器的话,浏览器——工具——选项(非Internet选项)——高级设置——FLASH, 默认使用PPAPI Flash(需要重启浏览器) 默认使用NPAPI Flash(需要重启浏览 ...

  6. test命令

    每一种条件语句的基础都是判断什么是真什么是假.是否了解其工作原理将决定您编写的是质量一般的脚本还是您将引以为荣的脚本.Shell 脚本的能力时常被低估,但实际上其能力的发挥受制于脚本撰写者的能力.您了 ...

  7. 详细讲解MOSFET管驱动电路(转)

    作者:   来源:电源网 关键字:MOSFET 结构 开关 驱动电路 在使用MOS管设计开关电源或者马达驱动电路的时候,大部分人都会考虑MOS的导通电阻,最大电压等,最大电流等,也有很多人仅仅考虑这些 ...

  8. 判断非法字符串的类方法,与jsp

    private String_do_judge judge; if (judge.isContain(key)) { return "feifa"; } 上面这写代码添加到进入ac ...

  9. 在Gridview编辑时添加DropDownList控件并设置默认值

    页面代码: <asp:GridView ID="GridView1" runat="server"             AutoGenerateCol ...

  10. 小红的难题<递推>

    题意:五个数:N,x,y,A,B;N是台阶总数,x,y是每步可以走x或者y步,但是一定要走到A,B台阶上. 思路:学长给的题解,递推,稍微优化一点. >重点在递推 #include<cst ...