[Angular Tutorial] 9 -Routing & Multiple Views
在这一步中,您将学到如何创建一个布局模板,并且学习怎样使用一个叫做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的更多相关文章
- Routing(路由) & Multiple Views(多个视图) step 7
Routing(路由) & Multiple Views(多个视图) step 7 1.切换分支到step7,并启动项目 git checkout step-7 npm start 2.需求: ...
- [Angular Tutorial]PhoneCat Tutorial App
(注:曾经在<不敢止步>一书中看到学到一个观点,作者认为学习一门技术最好的方法就是翻译某部领域书籍.这里我决定做一次尝试,接下来花1个月左右时间,将Angular Tutorial Pho ...
- AngularJS学习---Routing(路由) & Multiple Views(多个视图) step 7
1.切换分支到step7,并启动项目 git checkout step- npm start 2.需求: 在步骤7之前,应用只给我们的用户提供了一个简单的界面(一张所有手机的列表),并且所有的模板代 ...
- [Angular Tutorial] 3-Components
在先前的步骤中,我们看到了一个控制器和一个模板如何一起工作来将一个静态的HTML文件转化为动态页面(view).一般说来,这在单页应用中一种非常常见的模式(在Angular应用中尤其是这样): ·客户 ...
- [Angular Tutorial] 7-XHRs & Dependency Injection
我们受够了在应用中用硬编码的方法嵌入三部电话!现在让我们用Angular内建的叫做$http的服务来从我们的服务器获取更大的数据集吧.我们将会使用Angular的依赖注入来为PhoneListCtrl ...
- [Angular Tutorial] 0-Bootstraping
在这一节的tutorial中,您将会逐渐熟悉AngularJS phonecat app的最重要的源代码文件.您也将学到如何将开发服务器与angular-seed绑定到一起,并且在浏览器中运行应用. ...
- angular 2 - 004 routing 路由
https://angular.io/tutorial/toh-pt5 定义一个模块用来定义路由 src/app/app-routing.module.ts import { NgModule } f ...
- [Angular 2] Pipes with Multiple Parameters
Showing how to set up a Pipe that takes multiple updating inputs for multiple Component sources. imp ...
- [Angular Tutorial] 14 -Animations
在这一步中,我们将会通过在我们先前创建的模板代码中添加CSS和JavaScript动画效果来扩展我们的web应用. ·我们现在使用ngAnimate模块来允许动画效果贯穿整个应用. ·我们也依赖于自带 ...
随机推荐
- 第15章 I/O(输入/输出)
在变量.数组和对象中存储的数据是暂时存在的,程序结束后它们就会丢失.为了能够永久地保存创建的数据,需要将其保存在磁盘文件中,这样就可以在其它程序中使用它们.Java的I/O技术可以将数据保存到文本文件 ...
- AutoFac使用方法总结
AutoFac是.net平台下的IOC容器产品,它可以管理类之间的复杂的依赖关系.在使用方面主要是register和resolve两类操作. 这篇文章用单元测试的形式列举了AutoFac的常用使用方法 ...
- 使用iptraf,ifstat查看网络流量
1. 使用 iptraf iptraf是一个实时查看网络流量的文本屏幕界面工具. 有些系统不一定安装了, 如果是 RHEL,那么就去找安装盘中的 iptraf*.rpm 包安装: 如果是 CentOS ...
- FusionCharts参数大全及详细说明(中文)
概述:本文主要整理了FusionCharts图表控件所包含的各类参数(中文说明),包含了图表,字体,网格,数字格式等参数,便于大家在FusionCharts使用过程中查找所需要的各类参数. 本文主要整 ...
- Asp.Net MVC以 JSON传值扩展方法
Asp.Net在客户端和服务器端,以JSON形式相互传值,可写扩展方法,用到的类型如下: DataContractJsonSerializer类: 该类在System.Runtime.Serializ ...
- Qt5:不规则按钮的实现---通过贴图实现
在应用开发中,有时候为了美观会在UI界面中增加不规则的按钮 现在我们就来看看Qt中是怎么实现不规则按钮的 /////////////////////////////////////////////// ...
- MySQL5.7绿色版安装
1. 下载MySQL 5.7,地址:http://dev.mysql.com/downloads/mysql/ (选择32位或者64位版本需根据自身PC情况) 2. 下载后解压,比如我的目录结构是: ...
- android usb挂载分析----vold启动
http://blog.csdn.net/new_abc/article/details/7396733 前段时间做了下usb挂载的,现在出了几个bug,又要把流程给梳理下,顺便也把相关的知识总结下, ...
- [ERROR] Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist 160913 02:11:21 mysqld_safe mysqld from pid file /tmp/mysql.pid ended
-- :: [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0 -- :: [Warning] InnoDB: New ...
- Delphi 悬浮窗口、浮动窗口的实现
源:Delphi 悬浮窗口.浮动窗口的实现 浮动窗体的实现 http://blog.tianya.cn/blogger/post_show.asp?BlogID=68097&PostID=80 ...