翻译完了“升级”一章的新增部分
合并了测试索引 解决了移动设备上菜单显示不全的问题 文字微调
This commit is contained in:
parent
3c666d881e
commit
20bf6c0085
@ -105,6 +105,12 @@
|
|||||||
"intro": "废弃的Beta版路由"
|
"intro": "废弃的Beta版路由"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"router": {
|
||||||
|
"title": "路由与导航",
|
||||||
|
"intro": "揭示如何通过Angular 2路由进行基本的屏幕导航。",
|
||||||
|
"hide": true
|
||||||
|
},
|
||||||
|
|
||||||
"structural-directives": {
|
"structural-directives": {
|
||||||
"title": "结构型指令",
|
"title": "结构型指令",
|
||||||
"intro": "Angular有一个强力的模板引擎,它能让你轻松维护元素的DOM树结构。"
|
"intro": "Angular有一个强力的模板引擎,它能让你轻松维护元素的DOM树结构。"
|
||||||
|
@ -1,88 +1,194 @@
|
|||||||
:marked
|
:marked
|
||||||
We write **unit tests** to explore and confirm the **behavior** of parts of our application.
|
We write **unit tests** to explore and confirm the **behavior** of parts of our application.
|
||||||
|
|
||||||
我们编写**单元测试**来探索和确认我们应用程序的**行为**部分。
|
我们编写**单元测试**来探索并巩固应用程序中的**行为**部分。
|
||||||
|
|
||||||
1. They **guard** against breaking existing code (“regressions”) when we make changes.
|
1. They **guard** against breaking existing code (“regressions”) when we make changes.
|
||||||
1. 当我们改变代码是,它们**守护**已有代码,以防被破坏。
|
|
||||||
|
|
||||||
|
1. 当我们做出修改时,它们会**守护**已有代码(回归测试),防止其被破坏。
|
||||||
|
|
||||||
1. They **clarify** what the code does both when used as intended and when faced with deviant conditions.
|
1. They **clarify** what the code does both when used as intended and when faced with deviant conditions.
|
||||||
1. 在我们正确使用代码和面对异常情况时,它们**澄清**代码做什么。
|
|
||||||
|
|
||||||
|
1. 当我们正确使用代码和面对异常情况时,它们会让代码的用途更加**明晰**。
|
||||||
|
|
||||||
1. They **reveal** mistakes in design and implementation. Tests force us to look at our code from many angles. When a part of our application seems hard to test, we may have discovered a design flaw, something we can cure now rather than later when it becomes expensive to fix.
|
1. They **reveal** mistakes in design and implementation. Tests force us to look at our code from many angles. When a part of our application seems hard to test, we may have discovered a design flaw, something we can cure now rather than later when it becomes expensive to fix.
|
||||||
1. 它们**揭示**我们设计和实现的错误。测试强迫我们从多个角度看代码。当应用程序的一个部分看起来很难测试,我们可能会发现设计缺陷,这是我们可以立刻修复的,而不是等到它变得很难修复的时候。
|
|
||||||
|
1. 它们会**揭露**我们设计和实现中的错误。测试会强迫我们从多种角度看代码。如果应用程序的一个部分看起来很难测试,这可能就意味着存在设计缺陷。
|
||||||
|
我们可以立即修复它,而不用等到它变得不可收拾的那一天。
|
||||||
|
|
||||||
a(id="top")
|
a(id="top")
|
||||||
:marked
|
:marked
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
|
|
||||||
# 目录
|
# 目录
|
||||||
|
|
||||||
1. [Jasmine Testing 101](#jasmine-101)
|
1. [Jasmine Testing 101](#jasmine-101)
|
||||||
1. [Jasmine测试101](#jasmine-101)
|
|
||||||
|
1. [Jasmine测试简介](#jasmine-101)
|
||||||
|
|
||||||
- setup to run Jasmine tests in the browser
|
- setup to run Jasmine tests in the browser
|
||||||
- 设置浏览器来运行Jasmine测试
|
|
||||||
|
- 设置浏览器,来运行Jasmine测试
|
||||||
|
|
||||||
- basic Jasmine testing skills
|
- basic Jasmine testing skills
|
||||||
- 基础Jasmine测试技能
|
|
||||||
|
- Jasmine测试的基本技能
|
||||||
|
|
||||||
- write simple Jasmine tests in TypeScript
|
- write simple Jasmine tests in TypeScript
|
||||||
- 实用TypeScript来编写简单的Jasmine测试
|
|
||||||
|
- 用TypeScript编写简单的Jasmine测试
|
||||||
|
|
||||||
- debug a test in the browser
|
- debug a test in the browser
|
||||||
- 在浏览器里调试测试
|
|
||||||
|
|
||||||
|
- 在浏览器里调试一个测试
|
||||||
|
|
||||||
1. [The Application Under Test](#aut)
|
1. [The Application Under Test](#aut)
|
||||||
|
|
||||||
1. [被测试的应用程序](#aut)
|
1. [被测试的应用程序](#aut)
|
||||||
|
|
||||||
1. [First app test](#first-app-tests)
|
1. [First app test](#first-app-tests)
|
||||||
|
|
||||||
1. [第一个应用程序测试](#first-app-tests)
|
1. [第一个应用程序测试](#first-app-tests)
|
||||||
|
|
||||||
- test a simple application interface outside of Angular
|
- test a simple application interface outside of Angular
|
||||||
- 在Angular之外,测试一个简单的应用程序接口
|
|
||||||
- where to put the test file
|
|
||||||
- 测试文件存放到哪儿
|
|
||||||
- load a test file with systemJS
|
|
||||||
- 使用systemJS调用一个测试文件
|
|
||||||
|
|
||||||
|
- 在Angular之外,测试一个简单的应用程序接口
|
||||||
|
|
||||||
|
- where to put the test file
|
||||||
|
|
||||||
|
- 测试文件存放到哪儿
|
||||||
|
|
||||||
|
- load a test file with systemJS
|
||||||
|
|
||||||
|
- 使用systemJS调用一个测试文件
|
||||||
|
|
||||||
1. [Pipe driven development](#pipe-testing)
|
1. [Pipe driven development](#pipe-testing)
|
||||||
|
|
||||||
1. [测试驱动开发一个管道](#pipe-testing)
|
1. [测试驱动开发一个管道](#pipe-testing)
|
||||||
|
|
||||||
- create a test before creating a class
|
- create a test before creating a class
|
||||||
- 在新建类之前,新建一个测试
|
|
||||||
|
- 创建类之前,先创建一个测试
|
||||||
|
|
||||||
- load multiple test files in our test harness, using system.js
|
- load multiple test files in our test harness, using system.js
|
||||||
- 使用system.js,加载多个测试文件到我们的测试套装里
|
|
||||||
|
- 使用system.js,往我们的测试套件里加载多个测试文件
|
||||||
|
|
||||||
- add the Angular 2 library to our test harness
|
- add the Angular 2 library to our test harness
|
||||||
- 添加Angular 2的类库到我们的测试套装里
|
|
||||||
|
- 往我们的测试套件里添加Angular 2的类库
|
||||||
|
|
||||||
- watch the new test fail, and fix it
|
- watch the new test fail, and fix it
|
||||||
|
|
||||||
- 看着新测试失败,然后修复它
|
- 看着新测试失败,然后修复它
|
||||||
|
|
||||||
1. Test an Asynchronous Service (forthcoming)
|
1. Test an Asynchronous Service (forthcoming)
|
||||||
|
|
||||||
|
1. 测试异步服务(即将到来)
|
||||||
|
|
||||||
- test an asynchronous service class outside of Angular
|
- test an asynchronous service class outside of Angular
|
||||||
|
|
||||||
|
- 在Angular外测试异步服务类
|
||||||
|
|
||||||
- write a test plan in code
|
- write a test plan in code
|
||||||
|
|
||||||
|
- 用代码写测试计划
|
||||||
|
|
||||||
- fake a dependency
|
- fake a dependency
|
||||||
|
|
||||||
|
- 伪造一个依赖
|
||||||
|
|
||||||
- master the `catch(fail).then(done)` pattern
|
- master the `catch(fail).then(done)` pattern
|
||||||
|
|
||||||
|
- 掌握`catch(fail).then(done)`模式
|
||||||
|
|
||||||
- move setup to `beforeEach`
|
- move setup to `beforeEach`
|
||||||
|
|
||||||
|
- 把设置工作移入`beforeEach`
|
||||||
|
|
||||||
- test when a dependency fails
|
- test when a dependency fails
|
||||||
|
|
||||||
|
- 测试依赖失败时的情况
|
||||||
|
|
||||||
- control async test timeout
|
- control async test timeout
|
||||||
|
|
||||||
|
- 控制异步测试的超时时间
|
||||||
|
|
||||||
1. The Angular Test Environment (forthcoming)
|
1. The Angular Test Environment (forthcoming)
|
||||||
|
|
||||||
|
1. Angular测试环境(即将到来)
|
||||||
|
|
||||||
- the Angular test environment and why we need help
|
- the Angular test environment and why we need help
|
||||||
|
|
||||||
|
- Angular测试环境以及我们为什么需要它的帮助
|
||||||
|
|
||||||
- add the Angular Test libraries to the test harness
|
- add the Angular Test libraries to the test harness
|
||||||
|
|
||||||
|
- 把Angular测试库加入测试挽具中
|
||||||
|
|
||||||
- test the same async service using Angular Dependency Injection
|
- test the same async service using Angular Dependency Injection
|
||||||
|
|
||||||
|
- 使用Angular依赖注入测试同一个异步服务
|
||||||
|
|
||||||
- reduce friction with test helpers
|
- reduce friction with test helpers
|
||||||
|
|
||||||
|
- 减少与测试助手的摩擦
|
||||||
|
|
||||||
- introducing spies
|
- introducing spies
|
||||||
|
|
||||||
|
- 引入侦探类
|
||||||
|
|
||||||
1. Test a Component (forthcoming)
|
1. Test a Component (forthcoming)
|
||||||
- test the component outside of Angular
|
|
||||||
|
1. 测试组件(即将到来)
|
||||||
|
|
||||||
|
- test the component outside of Angular
|
||||||
|
|
||||||
|
- 在Angular外面测试组件
|
||||||
|
|
||||||
- mock the dependent asynchronous service
|
- mock the dependent asynchronous service
|
||||||
|
|
||||||
|
- 模拟所依赖的异步服务
|
||||||
|
|
||||||
- simulate interaction with the view (no DOM)
|
- simulate interaction with the view (no DOM)
|
||||||
|
|
||||||
|
- 仿真与视图的交互(不涉及DOM)
|
||||||
|
|
||||||
- use a spy-promise to control asynchronous test flow
|
- use a spy-promise to control asynchronous test flow
|
||||||
|
|
||||||
|
- 使用侦探型承诺(spy-promise)来控制异步测试工作流
|
||||||
|
|
||||||
1. Test a Component in the DOM (forthcoming
|
1. Test a Component in the DOM (forthcoming
|
||||||
- test the component inside the Angular test environment
|
|
||||||
- use the `TestComponentBuilder`
|
|
||||||
- more test helpers
|
|
||||||
- interact with the DOM
|
|
||||||
- bind to a mock dependent asynchronous service
|
|
||||||
|
|
||||||
|
1. 在DOM中测试组件(即将到来)
|
||||||
|
|
||||||
|
- test the component inside the Angular test environment
|
||||||
|
|
||||||
|
- 在Angular测试环境中测试组件
|
||||||
|
|
||||||
|
- use the `TestComponentBuilder`
|
||||||
|
|
||||||
|
- 使用`TestComponentBuilder`
|
||||||
|
|
||||||
|
- more test helpers
|
||||||
|
|
||||||
|
- 更多测试助手
|
||||||
|
|
||||||
|
- interact with the DOM
|
||||||
|
|
||||||
|
- 与DOM交互
|
||||||
|
|
||||||
|
- bind to a mock dependent asynchronous service
|
||||||
|
|
||||||
|
- 绑定到一个模拟的异步服务
|
||||||
|
|
||||||
1. Run the tests with karma (forthcoming)
|
1. Run the tests with karma (forthcoming)
|
||||||
|
|
||||||
|
1. 用Karma运行测试(即将到来)
|
||||||
|
|
||||||
It’s a big agenda. Fortunately, you can learn a little bit at a time and put each lesson to use.
|
It’s a big agenda. Fortunately, you can learn a little bit at a time and put each lesson to use.
|
||||||
|
|
||||||
|
这是一个很大的日程表。幸运的是,我们可以一次只学一小点,然后把它们投入实战。
|
||||||
|
|
||||||
a(href="#top").to-top Back to top
|
a(href="#top").to-top Back to top
|
||||||
|
|
||||||
@ -90,37 +196,49 @@ a(href="#top").to-top Back to top
|
|||||||
a(id="jasmine-101")
|
a(id="jasmine-101")
|
||||||
:marked
|
:marked
|
||||||
# Jasmine Testing 101
|
# Jasmine Testing 101
|
||||||
# Jasmine测试101
|
|
||||||
|
# Jasmine测试简介
|
||||||
|
|
||||||
!= partial("../testing/jasmine-testing-101")
|
!= partial("../testing/jasmine-testing-101")
|
||||||
a(href="#top").to-top Back to top
|
a(href="#top").to-top Back to top
|
||||||
|
a(href="#top").to-top 回到顶部
|
||||||
|
|
||||||
.l-hr
|
.l-hr
|
||||||
a(id="aut")
|
a(id="aut")
|
||||||
:marked
|
:marked
|
||||||
# The Application to Test
|
# The Application to Test
|
||||||
|
|
||||||
# 被测试的应用程序
|
# 被测试的应用程序
|
||||||
|
|
||||||
!= partial("../testing/application-under-test")
|
!= partial("../testing/application-under-test")
|
||||||
a(href="#top").to-top Back to top
|
a(href="#top").to-top Back to top
|
||||||
|
a(href="#top").to-top 回到顶部
|
||||||
|
|
||||||
.l-hr
|
.l-hr
|
||||||
a(id="first-app-tests")
|
a(id="first-app-tests")
|
||||||
:marked
|
:marked
|
||||||
# First app test
|
# First app test
|
||||||
|
|
||||||
# 第一个应用程序测试
|
# 第一个应用程序测试
|
||||||
|
|
||||||
!= partial("../testing/first-app-tests")
|
!= partial("../testing/first-app-tests")
|
||||||
a(href="#top").to-top Back to top
|
a(href="#top").to-top Back to top
|
||||||
|
a(href="#top").to-top 回到顶部
|
||||||
|
|
||||||
.l-hr
|
.l-hr
|
||||||
a(id="pipe-testing")
|
a(id="pipe-testing")
|
||||||
:marked
|
:marked
|
||||||
# Pipe driven development
|
# Pipe driven development
|
||||||
|
|
||||||
# 测试驱动开发一个管道
|
# 测试驱动开发一个管道
|
||||||
|
|
||||||
!= partial("../testing/testing-an-angular-pipe")
|
!= partial("../testing/testing-an-angular-pipe")
|
||||||
a(href="#top").to-top Back to top
|
a(href="#top").to-top Back to top
|
||||||
|
a(href="#top").to-top 回到顶部
|
||||||
|
|
||||||
.alert.is-important
|
.alert.is-important
|
||||||
:marked
|
:marked
|
||||||
The testing chapter is still under development.
|
The testing chapter is still under development.
|
||||||
Please bear with us as we both update and complete it.
|
Please bear with us as we both update and complete it.
|
||||||
|
|
||||||
测试章节正在开发中,请耐心,我们会更新并完成它。
|
测试章节正在开发中,请耐心,我们会更新并完成它。
|
||||||
|
@ -226,7 +226,7 @@ include ../_util-fns
|
|||||||
* JavaScript features new to ES2015, like arrow functions, `let`s and `const`s,
|
* JavaScript features new to ES2015, like arrow functions, `let`s and `const`s,
|
||||||
default function parameters, and destructuring assignments can also be gradually
|
default function parameters, and destructuring assignments can also be gradually
|
||||||
added to make the code more expressive.
|
added to make the code more expressive.
|
||||||
|
|
||||||
* 那些ES2015中新增的特性,比如箭头函数、`let`、`const`、默认函数参数、解构赋值等也能逐渐添加进来,让代码更有表现力。
|
* 那些ES2015中新增的特性,比如箭头函数、`let`、`const`、默认函数参数、解构赋值等也能逐渐添加进来,让代码更有表现力。
|
||||||
|
|
||||||
* Services and controllers can be turned into *classes*. That way they'll be a step
|
* Services and controllers can be turned into *classes*. That way they'll be a step
|
||||||
@ -353,7 +353,7 @@ include ../_util-fns
|
|||||||
are another convenient feature that Angular 1.5 introduces. They all have nearly
|
are another convenient feature that Angular 1.5 introduces. They all have nearly
|
||||||
exact [equivalents in Angular 2](lifecycle-hooks.html), so organizing component lifecycle
|
exact [equivalents in Angular 2](lifecycle-hooks.html), so organizing component lifecycle
|
||||||
logic around them will ease the eventual Angular 2 upgrade process.
|
logic around them will ease the eventual Angular 2 upgrade process.
|
||||||
|
|
||||||
控制器的生命周期钩子`$onInit()`、`$onDestroy()`和`$onChanges()`是Angular 1.5引入的另一些便利特性。
|
控制器的生命周期钩子`$onInit()`、`$onDestroy()`和`$onChanges()`是Angular 1.5引入的另一些便利特性。
|
||||||
它们都很接近于[Angular 2中的等价物](lifecycle-hooks.html),所以,围绕它们组织组件生命周期的逻辑会更容易升级。
|
它们都很接近于[Angular 2中的等价物](lifecycle-hooks.html),所以,围绕它们组织组件生命周期的逻辑会更容易升级。
|
||||||
|
|
||||||
@ -798,7 +798,7 @@ figure
|
|||||||
Note that even though we are in an Angular 1 template, **we're using Angular 2
|
Note that even though we are in an Angular 1 template, **we're using Angular 2
|
||||||
attribute syntax to bind the inputs and outputs**. This is a requirement for downgraded
|
attribute syntax to bind the inputs and outputs**. This is a requirement for downgraded
|
||||||
components. The expressions themselves are still regular Angular 1 expressions.
|
components. The expressions themselves are still regular Angular 1 expressions.
|
||||||
|
|
||||||
注意,虽然我们正在Angular 1的模板中,**但却在使用Angular 2的属性(Attribute)语法来绑定到输入属性与输出属性**。
|
注意,虽然我们正在Angular 1的模板中,**但却在使用Angular 2的属性(Attribute)语法来绑定到输入属性与输出属性**。
|
||||||
这是降级的组件本身要求的。而表达式本身仍然是标准的Angular 1表达式。
|
这是降级的组件本身要求的。而表达式本身仍然是标准的Angular 1表达式。
|
||||||
|
|
||||||
@ -809,16 +809,16 @@ figure
|
|||||||
There's one notable exception to the rule of using Angular 2 attribute syntax
|
There's one notable exception to the rule of using Angular 2 attribute syntax
|
||||||
for downgraded components. It has to do with input or output names that consist
|
for downgraded components. It has to do with input or output names that consist
|
||||||
of multiple words. In Angular 2 we would bind these attributes using camelCase:
|
of multiple words. In Angular 2 we would bind these attributes using camelCase:
|
||||||
|
|
||||||
为降级过的组件使用Angualr 2的属性(Attribute)语法规则时有一个值得注意的例外。
|
为降级过的组件使用Angualr 2的属性(Attribute)语法规则时有一个值得注意的例外。
|
||||||
它适用于由多个单词组成的输入或输出属性。在Angular 2中,我们要使用小驼峰命名法绑定这些属性:
|
它适用于由多个单词组成的输入或输出属性。在Angular 2中,我们要使用小驼峰命名法绑定这些属性:
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
[myHero]="hero"
|
[myHero]="hero"
|
||||||
:marked
|
:marked
|
||||||
But when using them from Angular 1 templates, we need to use kebab-case:
|
But when using them from Angular 1 templates, we need to use kebab-case:
|
||||||
|
|
||||||
但是从Angular 1的模板中使用它们时,我们得使用中线命名法:
|
但是从Angular 1的模板中使用它们时,我们得使用中线命名法:
|
||||||
|
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
[my-hero]="hero"
|
[my-hero]="hero"
|
||||||
|
|
||||||
@ -1147,7 +1147,7 @@ figure
|
|||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
# PhoneCat Upgrade Tutorial
|
# PhoneCat Upgrade Tutorial
|
||||||
|
|
||||||
# PhoneCat升级教程
|
# PhoneCat升级教程
|
||||||
|
|
||||||
In this section and we will look at a complete example of
|
In this section and we will look at a complete example of
|
||||||
@ -1239,7 +1239,7 @@ figure
|
|||||||
|
|
||||||
* Each component, service, and filter is in its own source file, as per the
|
* Each component, service, and filter is in its own source file, as per the
|
||||||
[Rule of 1](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#single-responsibility).
|
[Rule of 1](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#single-responsibility).
|
||||||
|
|
||||||
* 每个组件、服务和过滤器都在它自己的源文件中 —— 就像[规则1](https://github.com/johnpapa/angular-styleguide#single-responsibility)所要求的。
|
* 每个组件、服务和过滤器都在它自己的源文件中 —— 就像[规则1](https://github.com/johnpapa/angular-styleguide#single-responsibility)所要求的。
|
||||||
|
|
||||||
* The `core`, `phone-detail`, and `phone-list` modules are each in their
|
* The `core`, `phone-detail`, and `phone-list` modules are each in their
|
||||||
@ -1256,13 +1256,13 @@ figure
|
|||||||
* Unit tests are located side-by-side with application code where they are easily
|
* Unit tests are located side-by-side with application code where they are easily
|
||||||
found, as described in the rules for
|
found, as described in the rules for
|
||||||
[Organizing Tests](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#style-y197).
|
[Organizing Tests](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#style-y197).
|
||||||
|
|
||||||
* 单元测试都和应用代码在一起,它们很容易找到。就像规则
|
* 单元测试都和应用代码在一起,它们很容易找到。就像规则
|
||||||
[组织测试文件](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#style-y197)中要求的那样。
|
[组织测试文件](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#style-y197)中要求的那样。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
## Switching to TypeScript
|
## Switching to TypeScript
|
||||||
|
|
||||||
## 切换到TypeScript
|
## 切换到TypeScript
|
||||||
|
|
||||||
Since we're going to be writing our Angular 2 code in TypeScript, it makes sense to
|
Since we're going to be writing our Angular 2 code in TypeScript, it makes sense to
|
||||||
@ -1347,7 +1347,7 @@ code-example(format="").
|
|||||||
compiled JavaScript is what actually gets executed. If you start
|
compiled JavaScript is what actually gets executed. If you start
|
||||||
the project HTTP server with `npm start`, you should see the fully functional
|
the project HTTP server with `npm start`, you should see the fully functional
|
||||||
application in your browser.
|
application in your browser.
|
||||||
|
|
||||||
我们要做的下一件事是把JavaScript文件转换成TypeScript文件。
|
我们要做的下一件事是把JavaScript文件转换成TypeScript文件。
|
||||||
由于TypeScript是ECMAScript 2015的一个超集,而ES2015又是ECMAScript 5的超集,所以我们可以简单的把文件的扩展名从`.js`换成`.ts`,
|
由于TypeScript是ECMAScript 2015的一个超集,而ES2015又是ECMAScript 5的超集,所以我们可以简单的把文件的扩展名从`.js`换成`.ts`,
|
||||||
它们就还会像以前一样工作。由于TypeScript编译器仍在运行,它会为每一个`.ts`文件生成对应的`.js`文件,而真正运行的是编译后的`.js`文件。
|
它们就还会像以前一样工作。由于TypeScript编译器仍在运行,它会为每一个`.ts`文件生成对应的`.js`文件,而真正运行的是编译后的`.js`文件。
|
||||||
@ -1355,7 +1355,7 @@ code-example(format="").
|
|||||||
|
|
||||||
Now that we have TypeScript though, we can start benefiting from some of its
|
Now that we have TypeScript though, we can start benefiting from some of its
|
||||||
features. There's a lot of value the language can provide to Angular 1 applications.
|
features. There's a lot of value the language can provide to Angular 1 applications.
|
||||||
|
|
||||||
有了TypeScript,我们就可以从它的一些特性中获益了。此语言可以为Angular 1应用提供很多价值。
|
有了TypeScript,我们就可以从它的一些特性中获益了。此语言可以为Angular 1应用提供很多价值。
|
||||||
|
|
||||||
For one thing, TypeScript is a superset of ES2015. Any app that has previously
|
For one thing, TypeScript is a superset of ES2015. Any app that has previously
|
||||||
@ -1363,7 +1363,7 @@ code-example(format="").
|
|||||||
start incorporating all of the JavaScript features that are new to ES2015.
|
start incorporating all of the JavaScript features that are new to ES2015.
|
||||||
These include things like `let`s and `const`s, arrow functions, default function
|
These include things like `let`s and `const`s, arrow functions, default function
|
||||||
parameters, and destructuring assignments.
|
parameters, and destructuring assignments.
|
||||||
|
|
||||||
首先,TypeScript是一个ES2015的超集。任何以前用ES5写的程序(就像PhoneCat范例)都可以开始通过TypeScript
|
首先,TypeScript是一个ES2015的超集。任何以前用ES5写的程序(就像PhoneCat范例)都可以开始通过TypeScript
|
||||||
纳入那些添加到ES2015中的新特性。
|
纳入那些添加到ES2015中的新特性。
|
||||||
这包括`let`、`const`、箭头函数、函数默认参数以及解构(destructure)赋值。
|
这包括`let`、`const`、箭头函数、函数默认参数以及解构(destructure)赋值。
|
||||||
@ -1372,7 +1372,7 @@ code-example(format="").
|
|||||||
actually partially already happened because of the Angular 1 typings we installed.
|
actually partially already happened because of the Angular 1 typings we installed.
|
||||||
TypeScript are checking that we are calling Angular 1 APIs correctly when we do
|
TypeScript are checking that we are calling Angular 1 APIs correctly when we do
|
||||||
things like register components to Angular modules.
|
things like register components to Angular modules.
|
||||||
|
|
||||||
我们能做的另一件事就是把*类型安全*添加到代码中。这实际上已经部分完成了,因为我们已经安装了Angular 1的类型定义。
|
我们能做的另一件事就是把*类型安全*添加到代码中。这实际上已经部分完成了,因为我们已经安装了Angular 1的类型定义。
|
||||||
当我们正确调用Angular 1的API时,TypeScript会帮我们检查它 —— 比如王Angular模块中添加组件。
|
当我们正确调用Angular 1的API时,TypeScript会帮我们检查它 —— 比如王Angular模块中添加组件。
|
||||||
|
|
||||||
@ -1380,7 +1380,7 @@ code-example(format="").
|
|||||||
out of TypeScript's type system. For instance, we can annotate the checkmark
|
out of TypeScript's type system. For instance, we can annotate the checkmark
|
||||||
filter so that it explicitly expects booleans as arguments. This makes it clearer
|
filter so that it explicitly expects booleans as arguments. This makes it clearer
|
||||||
what the filter is supposed to do.
|
what the filter is supposed to do.
|
||||||
|
|
||||||
我们还能开始把*类型注解*添加到自己的代码中,来从TypeScript的类型系统中获得更多帮助。
|
我们还能开始把*类型注解*添加到自己的代码中,来从TypeScript的类型系统中获得更多帮助。
|
||||||
比如,我们可以给`checkmark`过滤器加上注解,表明它期待一个`boolean`类型的参数。
|
比如,我们可以给`checkmark`过滤器加上注解,表明它期待一个`boolean`类型的参数。
|
||||||
这可以更清楚的表明此过滤器打算做什么
|
这可以更清楚的表明此过滤器打算做什么
|
||||||
@ -1390,7 +1390,7 @@ code-example(format="").
|
|||||||
:marked
|
:marked
|
||||||
In the `Phone` service we can explicitly annotate the `$resource` service dependency
|
In the `Phone` service we can explicitly annotate the `$resource` service dependency
|
||||||
as an `angular.resource.IResourceService` - a type defined by the Angular 1 typings.
|
as an `angular.resource.IResourceService` - a type defined by the Angular 1 typings.
|
||||||
|
|
||||||
在`Phone`服务中,我们可以明确的把`$resource`服务声明为`angular.resource.IResourceService`一个在Angular 1类型定义中提供的类型。
|
在`Phone`服务中,我们可以明确的把`$resource`服务声明为`angular.resource.IResourceService`一个在Angular 1类型定义中提供的类型。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-1-typescript/ts/app/core/phone/phone.service.ts', null, 'app/core/phone/phone.service.ts')
|
+makeExample('upgrade-phonecat-1-typescript/ts/app/core/phone/phone.service.ts', null, 'app/core/phone/phone.service.ts')
|
||||||
@ -1399,7 +1399,7 @@ code-example(format="").
|
|||||||
We can apply the same trick to the application's route configuration file in `app.config.ts`,
|
We can apply the same trick to the application's route configuration file in `app.config.ts`,
|
||||||
where we are using the location and route services. By annotating them accordingly TypeScript
|
where we are using the location and route services. By annotating them accordingly TypeScript
|
||||||
can verify we're calling their APIs with the correct kinds of arguments.
|
can verify we're calling their APIs with the correct kinds of arguments.
|
||||||
|
|
||||||
我们可以在应用的路由配置中使用同样的技巧,那里我们用到了location和route服务。
|
我们可以在应用的路由配置中使用同样的技巧,那里我们用到了location和route服务。
|
||||||
一旦给它们提供了类型信息,TypeScript就能检查我们是否在用类型正确的参数来调用它们了。
|
一旦给它们提供了类型信息,TypeScript就能检查我们是否在用类型正确的参数来调用它们了。
|
||||||
|
|
||||||
@ -1411,7 +1411,7 @@ code-example(format="").
|
|||||||
we installed with Typings are not officially maintained by the Angular team,
|
we installed with Typings are not officially maintained by the Angular team,
|
||||||
but are quite comprehensive. It is possible to make an Angular 1.x application
|
but are quite comprehensive. It is possible to make an Angular 1.x application
|
||||||
fully type-annotated with the help of these definitions.
|
fully type-annotated with the help of these definitions.
|
||||||
|
|
||||||
我们用typings工具安装的这个[Angular 1.x类型定义文件](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/angularjs)
|
我们用typings工具安装的这个[Angular 1.x类型定义文件](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/angularjs)
|
||||||
并不是由Angular开发组维护的,但它也已经足够全面了。借助这些类型定义的帮助,它可以为Angular 1.x程序加上全面的类型注解。
|
并不是由Angular开发组维护的,但它也已经足够全面了。借助这些类型定义的帮助,它可以为Angular 1.x程序加上全面的类型注解。
|
||||||
|
|
||||||
@ -1442,7 +1442,7 @@ code-example(format="").
|
|||||||
这也就意味着只要我们把一个类注册为组件控制器,Angular 1就会愉快的使用它。
|
这也就意味着只要我们把一个类注册为组件控制器,Angular 1就会愉快的使用它。
|
||||||
|
|
||||||
Here's what our new class for the phone list component controller looks like:
|
Here's what our new class for the phone list component controller looks like:
|
||||||
|
|
||||||
新的“电话列表(phone list)”组件控制器类看起来是这样的:
|
新的“电话列表(phone list)”组件控制器类看起来是这样的:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat/ts/classes/app/js/phone_list/phone_list.controller.ts', null, 'app/js/phone_list/phone_list.controller.ts')
|
+makeExample('upgrade-phonecat/ts/classes/app/js/phone_list/phone_list.controller.ts', null, 'app/js/phone_list/phone_list.controller.ts')
|
||||||
@ -1462,14 +1462,14 @@ code-example(format="").
|
|||||||
The last one of these isn't actually used in the TypeScript code since it's only
|
The last one of these isn't actually used in the TypeScript code since it's only
|
||||||
referred to in the template, but for the sake of clarity we want to define all the
|
referred to in the template, but for the sake of clarity we want to define all the
|
||||||
members our controller will have.
|
members our controller will have.
|
||||||
|
|
||||||
该类额外声明了三个成员:电话列表、当前排序键的名字,以及搜索条件。
|
该类额外声明了三个成员:电话列表、当前排序键的名字,以及搜索条件。
|
||||||
这些东西我们以前就加到了控制器上,只是从来没有在任何地方显式定义过它们。最后一个成员从未真正在TypeScript代码中用过,
|
这些东西我们以前就加到了控制器上,只是从来没有在任何地方显式定义过它们。最后一个成员从未真正在TypeScript代码中用过,
|
||||||
因为它只是在模板中被引用过。但为了清晰起见,我们还是该定义出此控制器应有的所有成员。
|
因为它只是在模板中被引用过。但为了清晰起见,我们还是该定义出此控制器应有的所有成员。
|
||||||
|
|
||||||
In the Phone detail controller we'll have two members: One for the phone
|
In the Phone detail controller we'll have two members: One for the phone
|
||||||
that the user is looking at and another for the URL of the currently displayed image:
|
that the user is looking at and another for the URL of the currently displayed image:
|
||||||
|
|
||||||
在电话详情控制器中,我们有两个成员:一个是用户正在查看的电话,另一个是正在显示的图像:
|
在电话详情控制器中,我们有两个成员:一个是用户正在查看的电话,另一个是正在显示的图像:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-1-typescript/ts/app/phone-detail/phone-detail.component.ts', null, 'app/phone-detail/phone-detail.component.ts')
|
+makeExample('upgrade-phonecat-1-typescript/ts/app/phone-detail/phone-detail.component.ts', null, 'app/phone-detail/phone-detail.component.ts')
|
||||||
@ -1512,17 +1512,17 @@ code-example(format="").
|
|||||||
|
|
||||||
我们来使用SystemJS模块加载器把Angular 2安装到项目中。
|
我们来使用SystemJS模块加载器把Angular 2安装到项目中。
|
||||||
看看[“快速起步”](../quickstart.html)中的指南,并从那里获得如下配置:
|
看看[“快速起步”](../quickstart.html)中的指南,并从那里获得如下配置:
|
||||||
|
|
||||||
* Add Angular 2 and the other new dependencies to `package.json`
|
* Add Angular 2 and the other new dependencies to `package.json`
|
||||||
|
|
||||||
* 把添加Angular 2和其它新依赖添加到`package.json`中
|
* 把添加Angular 2和其它新依赖添加到`package.json`中
|
||||||
|
|
||||||
* Add the new typings into `typings.json`
|
* Add the new typings into `typings.json`
|
||||||
|
|
||||||
* 把这些新的类型定义添加到`typings.json`中
|
* 把这些新的类型定义添加到`typings.json`中
|
||||||
|
|
||||||
* The SystemJS configuration file `systemjs.config.js` to the project root directory.
|
* The SystemJS configuration file `systemjs.config.js` to the project root directory.
|
||||||
|
|
||||||
* 把SystemJS的配置文件`systemjs.config.js`添加到项目的根目录。
|
* 把SystemJS的配置文件`systemjs.config.js`添加到项目的根目录。
|
||||||
|
|
||||||
Once these are done, run:
|
Once these are done, run:
|
||||||
@ -1538,14 +1538,14 @@ code-example(format="").
|
|||||||
but first we need to do some directory path adjustments. This is because we're going
|
but first we need to do some directory path adjustments. This is because we're going
|
||||||
to need to load files from `node_modules` and the project root, whereas so far
|
to need to load files from `node_modules` and the project root, whereas so far
|
||||||
in this project everything has been loaded from the `/app` directory.
|
in this project everything has been loaded from the `/app` directory.
|
||||||
|
|
||||||
我们可以通过`index.html`来把Angular 2的依赖快速加载到应用中,
|
我们可以通过`index.html`来把Angular 2的依赖快速加载到应用中,
|
||||||
但首先,我们得做一些目录结构调整。这是因为我们正准备从`node_modules`中加载文件,然而目前项目中的每一个文件都是从`/app`目录下加载的。
|
但首先,我们得做一些目录结构调整。这是因为我们正准备从`node_modules`中加载文件,然而目前项目中的每一个文件都是从`/app`目录下加载的。
|
||||||
|
|
||||||
Move the `app/index.html` file to the project root directory. Then change the
|
Move the `app/index.html` file to the project root directory. Then change the
|
||||||
development server root path in `package.json` to also point to the project root
|
development server root path in `package.json` to also point to the project root
|
||||||
instead of `app`:
|
instead of `app`:
|
||||||
|
|
||||||
把`app/index.html`移入项目的根目录,然后把`package.json`中的开发服务器根目录也指向项目的根目录,而不再是`app`目录:
|
把`app/index.html`移入项目的根目录,然后把`package.json`中的开发服务器根目录也指向项目的根目录,而不再是`app`目录:
|
||||||
|
|
||||||
+makeJson('upgrade-phonecat-2-hybrid/ts/package.ng1.json', {paths: 'scripts.start'}, 'package.json')
|
+makeJson('upgrade-phonecat-2-hybrid/ts/package.ng1.json', {paths: 'scripts.start'}, 'package.json')
|
||||||
@ -1555,7 +1555,7 @@ code-example(format="").
|
|||||||
want to have to change all the image and data paths used in the application code to match
|
want to have to change all the image and data paths used in the application code to match
|
||||||
our development setup. For that reason, we'll add a `<base>` tag to `index.html`, which will
|
our development setup. For that reason, we'll add a `<base>` tag to `index.html`, which will
|
||||||
cause relative URLs to be resolved back to the `/app` directory:
|
cause relative URLs to be resolved back to the `/app` directory:
|
||||||
|
|
||||||
现在,我们能把项目根目录下的每一样东西发给浏览器了。但我们并不想修改在应用代码中用到的每一个图片和数据的路径,
|
现在,我们能把项目根目录下的每一样东西发给浏览器了。但我们并不想修改在应用代码中用到的每一个图片和数据的路径,
|
||||||
以适应我们开发环境中的设置。因此,我们往`index.html`中添加一个`<base>`标签,它将导致各种相对路径被解析回`/app`目录:
|
以适应我们开发环境中的设置。因此,我们往`index.html`中添加一个`<base>`标签,它将导致各种相对路径被解析回`/app`目录:
|
||||||
|
|
||||||
@ -1565,7 +1565,7 @@ code-example(format="").
|
|||||||
Now we can load Angular 2 via SystemJS. We'll add the Angular 2 polyfills and the
|
Now we can load Angular 2 via SystemJS. We'll add the Angular 2 polyfills and the
|
||||||
SystemJS config to the end of the `<head>` section, and then we'll use `System.import`
|
SystemJS config to the end of the `<head>` section, and then we'll use `System.import`
|
||||||
to load the actual application:
|
to load the actual application:
|
||||||
|
|
||||||
现在我们可以通过SystemJS加载Angular 2了。我们将把Angular 2的填充库(polyfills)
|
现在我们可以通过SystemJS加载Angular 2了。我们将把Angular 2的填充库(polyfills)
|
||||||
和SystemJS的配置加到`<head>`区的末尾,然后,我们就用`System.import`来加载实际的应用:
|
和SystemJS的配置加到`<head>`区的末尾,然后,我们就用`System.import`来加载实际的应用:
|
||||||
|
|
||||||
@ -1575,7 +1575,7 @@ code-example(format="").
|
|||||||
In the `systemjs.config.js` file we got from the Quickstart we also need to make a couple
|
In the `systemjs.config.js` file we got from the Quickstart we also need to make a couple
|
||||||
of adjustments because of our project structure. We want to point the browser to the project
|
of adjustments because of our project structure. We want to point the browser to the project
|
||||||
root when loading things through SystemJS, instead of using the `<base>` URL:
|
root when loading things through SystemJS, instead of using the `<base>` URL:
|
||||||
|
|
||||||
在我们从“快速起步”中拿来的`systemjs.config.js`文件中,我们还需要做一些调整,以适应我们的项目结构。
|
在我们从“快速起步”中拿来的`systemjs.config.js`文件中,我们还需要做一些调整,以适应我们的项目结构。
|
||||||
在使用SystemJS而不是`<base>` URL加载时,我们需要把浏览器指向项目的根目录。
|
在使用SystemJS而不是`<base>` URL加载时,我们需要把浏览器指向项目的根目录。
|
||||||
|
|
||||||
@ -1588,7 +1588,7 @@ code-example(format="").
|
|||||||
What we'll do next is bootstrap the application as a *hybrid application*
|
What we'll do next is bootstrap the application as a *hybrid application*
|
||||||
that supports both Angular 1 and Angular 2 components. Once we've done that
|
that supports both Angular 1 and Angular 2 components. Once we've done that
|
||||||
we can start converting the individual pieces to Angular 2.
|
we can start converting the individual pieces to Angular 2.
|
||||||
|
|
||||||
我们后面将做的就是把该应用程序引导为一个同时支持Angular 1和Angular 2的*混合式应用*。
|
我们后面将做的就是把该应用程序引导为一个同时支持Angular 1和Angular 2的*混合式应用*。
|
||||||
一旦我们做完了,就能开始把这些不可分割的小块儿转换到Angular 2了.
|
一旦我们做完了,就能开始把这些不可分割的小块儿转换到Angular 2了.
|
||||||
|
|
||||||
@ -1597,7 +1597,7 @@ code-example(format="").
|
|||||||
versions of the framework together. Let's import the `UpgradeAdapter` class into a
|
versions of the framework together. Let's import the `UpgradeAdapter` class into a
|
||||||
new file `app/main.ts`. This file has been configured as the application entrypoint
|
new file `app/main.ts`. This file has been configured as the application entrypoint
|
||||||
in `systemjs.config.js`, so it is already being loaded by the browser.
|
in `systemjs.config.js`, so it is already being loaded by the browser.
|
||||||
|
|
||||||
要引导一个混合式应用,我们首先得初始化一个`UpgradeAdapter`,它[提供了胶水](#upgrading-with-the-upgrade-adapter)
|
要引导一个混合式应用,我们首先得初始化一个`UpgradeAdapter`,它[提供了胶水](#upgrading-with-the-upgrade-adapter)
|
||||||
来把框架的两个不同版本粘在一起。我们在一个新文件`app/main.ts`中导入`UpgradeAdapter`类。
|
来把框架的两个不同版本粘在一起。我们在一个新文件`app/main.ts`中导入`UpgradeAdapter`类。
|
||||||
这个文件已经在`systemjs.config.js`文件中被配置成了应用的入口点,所以它已经被浏览器加载了。
|
这个文件已经在`systemjs.config.js`文件中被配置成了应用的入口点,所以它已经被浏览器加载了。
|
||||||
@ -1616,7 +1616,7 @@ code-example(format="").
|
|||||||
attached to the `<html>` element of the host page. This will no longer work with
|
attached to the `<html>` element of the host page. This will no longer work with
|
||||||
Angular 2. We should switch to a JavaScript-driven bootstrap instead. So, remove the
|
Angular 2. We should switch to a JavaScript-driven bootstrap instead. So, remove the
|
||||||
`ng-app` attribute from `index.html`, and instead add this to `main.ts`:
|
`ng-app` attribute from `index.html`, and instead add this to `main.ts`:
|
||||||
|
|
||||||
我们的应用现在是使用宿主页面中附加到`<html>`元素上的`ng-app`指令引导的。
|
我们的应用现在是使用宿主页面中附加到`<html>`元素上的`ng-app`指令引导的。
|
||||||
但在Angular 2中,它不再工作了。我们得切换成JavaScript驱动的引导方式。
|
但在Angular 2中,它不再工作了。我们得切换成JavaScript驱动的引导方式。
|
||||||
所以,从`index.html`中移除`ng-app`属性,并把这些加载`main.ts`中:
|
所以,从`index.html`中移除`ng-app`属性,并把这些加载`main.ts`中:
|
||||||
@ -1629,7 +1629,7 @@ code-example(format="").
|
|||||||
that we want to load. Since we're bootstrapping the app through
|
that we want to load. Since we're bootstrapping the app through
|
||||||
an `UpgradeAdapter`, we're actually now running the app as a hybrid Angular 1+2
|
an `UpgradeAdapter`, we're actually now running the app as a hybrid Angular 1+2
|
||||||
app.
|
app.
|
||||||
|
|
||||||
这里使用的参数是应用的根元素(也就是以前我们放`ng-app`的元素),和我们准备加载的Angular 1.x模块。
|
这里使用的参数是应用的根元素(也就是以前我们放`ng-app`的元素),和我们准备加载的Angular 1.x模块。
|
||||||
由于我们是通过`UpgradeAdapter`引导应用的,所以实际在运行的应用实际上是一个Angular 1+2的混合体。
|
由于我们是通过`UpgradeAdapter`引导应用的,所以实际在运行的应用实际上是一个Angular 1+2的混合体。
|
||||||
|
|
||||||
@ -1753,7 +1753,7 @@ code-example(format="").
|
|||||||
`UpgradeAdapter` has a `downgradeNg2Provider` method for the purpose of making
|
`UpgradeAdapter` has a `downgradeNg2Provider` method for the purpose of making
|
||||||
Angular 2 services available to Angular 1 code. We can use it to plug in our
|
Angular 2 services available to Angular 1 code. We can use it to plug in our
|
||||||
`Phone` service:
|
`Phone` service:
|
||||||
|
|
||||||
`UpgradeAdapter`有个`downgradeNg2Provider`方法就是用来让Angular 2的服务在Angular 1的代码中可用的。
|
`UpgradeAdapter`有个`downgradeNg2Provider`方法就是用来让Angular 2的服务在Angular 1的代码中可用的。
|
||||||
我们可以使用它来插入我们的`Phone`服务:
|
我们可以使用它来插入我们的`Phone`服务:
|
||||||
|
|
||||||
@ -1766,19 +1766,19 @@ code-example(format="").
|
|||||||
|
|
||||||
1. Register `Phone` as an **Angular 2 provider** with the `addProvider`
|
1. Register `Phone` as an **Angular 2 provider** with the `addProvider`
|
||||||
method. That's the same method that we used earlier for `HTTP_PROVIDERS`.
|
method. That's the same method that we used earlier for `HTTP_PROVIDERS`.
|
||||||
|
|
||||||
1. 用`addProvider`方法注册了一个名叫`Phone`的**Angular 2供应商**。这和我们以前使用`HTTP_PROVIDERS`的方法一样。
|
1. 用`addProvider`方法注册了一个名叫`Phone`的**Angular 2供应商**。这和我们以前使用`HTTP_PROVIDERS`的方法一样。
|
||||||
|
|
||||||
2. Register an **Angular 1 factory** called `phone`, which will be a *downgraded*
|
2. Register an **Angular 1 factory** called `phone`, which will be a *downgraded*
|
||||||
version of the `Phone` Angular 2 service.
|
version of the `Phone` Angular 2 service.
|
||||||
|
|
||||||
2. 注册了一个名叫`phone`的**Angular 1工厂**,它是一个`Phones`服务的*降级*版。
|
2. 注册了一个名叫`phone`的**Angular 1工厂**,它是一个`Phones`服务的*降级*版。
|
||||||
|
|
||||||
Now that we are loading `phone.service.ts` through an import that is resolved
|
Now that we are loading `phone.service.ts` through an import that is resolved
|
||||||
by SystemJS, we should **remove the `<script>` tag** for the service from `index.html`.
|
by SystemJS, we should **remove the `<script>` tag** for the service from `index.html`.
|
||||||
This is something we'll do to all our components as we upgrade them. Simultaneously
|
This is something we'll do to all our components as we upgrade them. Simultaneously
|
||||||
with the Angular 1 to 2 upgrade we're also migrating our code from scripts to modules.
|
with the Angular 1 to 2 upgrade we're also migrating our code from scripts to modules.
|
||||||
|
|
||||||
现在,我们正在用SystemJS加载`phone.service.ts`,我们应该从`index.html`中**移除该服务的`<script>`标签**。
|
现在,我们正在用SystemJS加载`phone.service.ts`,我们应该从`index.html`中**移除该服务的`<script>`标签**。
|
||||||
这也是我们在升级所有组件时将会做的事。在从Angular 1向2升级的同时,我们也把代码从脚本移植为模块。
|
这也是我们在升级所有组件时将会做的事。在从Angular 1向2升级的同时,我们也把代码从脚本移植为模块。
|
||||||
|
|
||||||
@ -1786,7 +1786,7 @@ code-example(format="").
|
|||||||
instead of the old one. We `$inject` it as the downgraded `phone` factory,
|
instead of the old one. We `$inject` it as the downgraded `phone` factory,
|
||||||
but it's really an instance of the `Phone` class and we can annotate its type
|
but it's really an instance of the `Phone` class and we can annotate its type
|
||||||
accordingly:
|
accordingly:
|
||||||
|
|
||||||
这时,我们可以把两个控制器从使用老的服务切换成使用新的。我们像降级过的`phones`工厂一样`$inject`它,
|
这时,我们可以把两个控制器从使用老的服务切换成使用新的。我们像降级过的`phones`工厂一样`$inject`它,
|
||||||
但它实际上是一个`Phones`类的实例,并且我们可以据此注解它的类型:
|
但它实际上是一个`Phones`类的实例,并且我们可以据此注解它的类型:
|
||||||
|
|
||||||
@ -1810,28 +1810,28 @@ code-example(format="").
|
|||||||
We could also use the `toPromise` method of `Observable` to turn those
|
We could also use the `toPromise` method of `Observable` to turn those
|
||||||
Observables into Promises in the service. This can in many cases further
|
Observables into Promises in the service. This can in many cases further
|
||||||
reduce the amount of changes needed in the component controllers.
|
reduce the amount of changes needed in the component controllers.
|
||||||
|
|
||||||
我们也能使用`Observable`的`toPromise`方法来在服务中把这些可观察对象转变成承诺,以进一步减小组件控制器中需要修改的代码量。
|
我们也能使用`Observable`的`toPromise`方法来在服务中把这些可观察对象转变成承诺,以进一步减小组件控制器中需要修改的代码量。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
## Upgrading Components
|
## Upgrading Components
|
||||||
|
|
||||||
## 升级组件
|
## 升级组件
|
||||||
|
|
||||||
Next, let's upgrade our Angular 1 components to Angular 2 components. We'll
|
Next, let's upgrade our Angular 1 components to Angular 2 components. We'll
|
||||||
do it one at a time, while still keeping the application in hybrid mode.
|
do it one at a time, while still keeping the application in hybrid mode.
|
||||||
As we make these conversions, we'll also be defining our first Angular 2 *pipes*.
|
As we make these conversions, we'll also be defining our first Angular 2 *pipes*.
|
||||||
|
|
||||||
接下来,我们把Angular 1的控制器升级成Angular 2的组件。我们每次升级一个,同时仍然保持应用运行在混合模式下。
|
接下来,我们把Angular 1的控制器升级成Angular 2的组件。我们每次升级一个,同时仍然保持应用运行在混合模式下。
|
||||||
在做转换的同时,我们还将自定义首个Angular 2*管道*。
|
在做转换的同时,我们还将自定义首个Angular 2*管道*。
|
||||||
|
|
||||||
|
|
||||||
Let's look at the phone list component first. Right now it contains a TypeScript
|
Let's look at the phone list component first. Right now it contains a TypeScript
|
||||||
controller class and a component definition object. We can morph this into
|
controller class and a component definition object. We can morph this into
|
||||||
an Angular 2 component by just renaming the controller class and turning the
|
an Angular 2 component by just renaming the controller class and turning the
|
||||||
Angular 1 component definition object into an Angular 2 `@Component` decorator.
|
Angular 1 component definition object into an Angular 2 `@Component` decorator.
|
||||||
We can then also remove the static `$inject` property from the class:
|
We can then also remove the static `$inject` property from the class:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts', 'initialclass', 'app/phone-list/phone-list.component.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts', 'initialclass', 'app/phone-list/phone-list.component.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -1839,7 +1839,7 @@ code-example(format="").
|
|||||||
should go. In Angular 1 we do matching based on component names, but in Angular 2 we
|
should go. In Angular 1 we do matching based on component names, but in Angular 2 we
|
||||||
have these explicit selectors. This one will match elements with the name `phone-list`,
|
have these explicit selectors. This one will match elements with the name `phone-list`,
|
||||||
just like the Angular 1 version did.
|
just like the Angular 1 version did.
|
||||||
|
|
||||||
We now also need to convert the template of this component into Angular 2 syntax.
|
We now also need to convert the template of this component into Angular 2 syntax.
|
||||||
In the search controls we need to use Angular 2 syntax for the two `ngModel`s.
|
In the search controls we need to use Angular 2 syntax for the two `ngModel`s.
|
||||||
We should also no longer use the `$ctrl` prefix in expressions:
|
We should also no longer use the `$ctrl` prefix in expressions:
|
||||||
@ -1851,7 +1851,7 @@ code-example(format="").
|
|||||||
`let var of iterable` syntax, which is [described in our
|
`let var of iterable` syntax, which is [described in our
|
||||||
Template Syntax guide](../guide/template-syntax.html#directives).
|
Template Syntax guide](../guide/template-syntax.html#directives).
|
||||||
For the images, we can replace `ng-src` with a binding to the standard `src` property.
|
For the images, we can replace `ng-src` with a binding to the standard `src` property.
|
||||||
|
|
||||||
在列表中,我们需要把`ng-repeat`替换为`*ngFor`以及它的`let var of iterable`语法,
|
在列表中,我们需要把`ng-repeat`替换为`*ngFor`以及它的`let var of iterable`语法,
|
||||||
该语法在[模板语法指南中讲过](../guide/template-syntax.html#directives)。
|
该语法在[模板语法指南中讲过](../guide/template-syntax.html#directives)。
|
||||||
对于图片,我们可以把`ng-src`替换为一个标准的`src`属性(property)绑定。
|
对于图片,我们可以把`ng-src`替换为一个标准的`src`属性(property)绑定。
|
||||||
@ -1866,7 +1866,7 @@ code-example(format="").
|
|||||||
pipes for this purpose, but in this case it is more convenient to just implement the filtering
|
pipes for this purpose, but in this case it is more convenient to just implement the filtering
|
||||||
and ordering logic in the component itself. We expect the `getPhones()` method to return a collection
|
and ordering logic in the component itself. We expect the `getPhones()` method to return a collection
|
||||||
where the current filtering and ordering has been applied.
|
where the current filtering and ordering has been applied.
|
||||||
|
|
||||||
我们在这里做的另一件事就是移除了`filter`和`orderBy`过滤器的使用,并把它们换成对控制器中`getPhones()`方法的调用。
|
我们在这里做的另一件事就是移除了`filter`和`orderBy`过滤器的使用,并把它们换成对控制器中`getPhones()`方法的调用。
|
||||||
内建的`filter`和`orderBy`在Angular 2中已经不存在了,所以我们得自己进行过滤和排序。
|
内建的`filter`和`orderBy`在Angular 2中已经不存在了,所以我们得自己进行过滤和排序。
|
||||||
我们可以为此定义自己的Angular 2管道,但是在这个案例中,在组件本身实现过滤和排序逻辑反倒更方便。
|
我们可以为此定义自己的Angular 2管道,但是在这个案例中,在组件本身实现过滤和排序逻辑反倒更方便。
|
||||||
@ -1894,12 +1894,12 @@ code-example(format="").
|
|||||||
降级方法(`downgradeNg2Component`)的返回值能作为指令工厂使用。
|
降级方法(`downgradeNg2Component`)的返回值能作为指令工厂使用。
|
||||||
|
|
||||||
At this point, also remove the `<script>` tag for the phone list component from `index.html`.
|
At this point, also remove the `<script>` tag for the phone list component from `index.html`.
|
||||||
|
|
||||||
这时,也从`index.html`中移除电话列表组件的`<script>`标签。
|
这时,也从`index.html`中移除电话列表组件的`<script>`标签。
|
||||||
|
|
||||||
Now we can start looking at our other component, which is the one for
|
Now we can start looking at our other component, which is the one for
|
||||||
the phone details. Set the contents of `phone-detail.component.ts` as follows:
|
the phone details. Set the contents of `phone-detail.component.ts` as follows:
|
||||||
|
|
||||||
现在我们可以开始看看另一个组件,那就是电话详情。把`phone-detail.component.ts`的内容设置为这样:
|
现在我们可以开始看看另一个组件,那就是电话详情。把`phone-detail.component.ts`的内容设置为这样:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts', 'initialclass', 'app/phone-detail/phone-detail.component.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts', 'initialclass', 'app/phone-detail/phone-detail.component.ts')
|
||||||
@ -1910,7 +1910,7 @@ code-example(format="").
|
|||||||
Angular 2 injector what this dependency should map to. We have a dependency called
|
Angular 2 injector what this dependency should map to. We have a dependency called
|
||||||
`$routeParams` in the Angular 1 injector, where it is provided by the Angular 1 router.
|
`$routeParams` in the Angular 1 injector, where it is provided by the Angular 1 router.
|
||||||
That is what we were already using when `PhoneDetails` was still an Angular 1 controller.
|
That is what we were already using when `PhoneDetails` was still an Angular 1 controller.
|
||||||
|
|
||||||
这和我们对电话列表所做的很相似。这里的一个新的更改是使用`@Inject`来获取`$routeParams`依赖。
|
这和我们对电话列表所做的很相似。这里的一个新的更改是使用`@Inject`来获取`$routeParams`依赖。
|
||||||
它告诉Angular 2的注入器这个依赖该被映射成什么。我们在Angular 1的注入器中有一个名叫`$routeParams`的依赖,
|
它告诉Angular 2的注入器这个依赖该被映射成什么。我们在Angular 1的注入器中有一个名叫`$routeParams`的依赖,
|
||||||
它是由Angular 1路由器提供的。
|
它是由Angular 1路由器提供的。
|
||||||
@ -1920,11 +1920,11 @@ code-example(format="").
|
|||||||
Angular 2 components, so if we were to run this now, it would not work. We need to explicitly
|
Angular 2 components, so if we were to run this now, it would not work. We need to explicitly
|
||||||
tell the `UpgradeAdapter` to upgrade `$routeParams` so that it is available for injection in
|
tell the `UpgradeAdapter` to upgrade `$routeParams` so that it is available for injection in
|
||||||
Angular 2. We can do it in `main.ts`:
|
Angular 2. We can do it in `main.ts`:
|
||||||
|
|
||||||
问题是,Angular 1的依赖不会自动对Angular 2的组件可用,所以如果我们现在运行它,它将无法工作。
|
问题是,Angular 1的依赖不会自动对Angular 2的组件可用,所以如果我们现在运行它,它将无法工作。
|
||||||
我们得显式的告诉`UpgradeAdapter`去升级`$routeParams`,以便它能被注入到Angular 2中。
|
我们得显式的告诉`UpgradeAdapter`去升级`$routeParams`,以便它能被注入到Angular 2中。
|
||||||
我们可以在`main.ts`中这么做:
|
我们可以在`main.ts`中这么做:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'routeparams', 'app/main.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'routeparams', 'app/main.ts')
|
||||||
|
|
||||||
|
|
||||||
@ -1949,7 +1949,7 @@ code-example(format="").
|
|||||||
|
|
||||||
* Just like we did in the phone list, we've replaced `ng-src` with property
|
* Just like we did in the phone list, we've replaced `ng-src` with property
|
||||||
bindings for the standard `src` property.
|
bindings for the standard `src` property.
|
||||||
|
|
||||||
* 正如我们在电话列表中做过的那样,我们把`ng-src`替换成了标准的`src`属性绑定。
|
* 正如我们在电话列表中做过的那样,我们把`ng-src`替换成了标准的`src`属性绑定。
|
||||||
|
|
||||||
* We're using the property binding syntax around `ng-class`. Though Angular 2
|
* We're using the property binding syntax around `ng-class`. Though Angular 2
|
||||||
@ -1977,7 +1977,7 @@ code-example(format="").
|
|||||||
non-existing value. Unlike in Angular 1, Angular 2 expressions do not fail silently
|
non-existing value. Unlike in Angular 1, Angular 2 expressions do not fail silently
|
||||||
when we try to refer to properties on undefined objects. We need to be explicit
|
when we try to refer to properties on undefined objects. We need to be explicit
|
||||||
about cases where this is expected.
|
about cases where this is expected.
|
||||||
|
|
||||||
* 我们把整个模板都包裹进了一个`ngIf`中,这导致只有当存在一个电话时它才会渲染。我们必须这么做,
|
* 我们把整个模板都包裹进了一个`ngIf`中,这导致只有当存在一个电话时它才会渲染。我们必须这么做,
|
||||||
是因为组件首次加载时我们还没有`phone`变量,这些表达式就会引用到一个不存在的值。
|
是因为组件首次加载时我们还没有`phone`变量,这些表达式就会引用到一个不存在的值。
|
||||||
和Angular 1不同,当我们尝试引用未定义对象上的属性时,Angular 2中的表达式不会默默失败。
|
和Angular 1不同,当我们尝试引用未定义对象上的属性时,Angular 2中的表达式不会默默失败。
|
||||||
@ -1987,7 +1987,7 @@ code-example(format="").
|
|||||||
In `main.ts` we'll now register a `phoneDetail` directive instead of a
|
In `main.ts` we'll now register a `phoneDetail` directive instead of a
|
||||||
component. The directive is a downgraded version of the `PhoneDetail` Angular 2
|
component. The directive is a downgraded version of the `PhoneDetail` Angular 2
|
||||||
component.
|
component.
|
||||||
|
|
||||||
在`main.ts`中,我们现在会注册一个`pcPhoneDetail`指令,而不再是组件。该指令是`PhoneDetail`组件的一个降级版。
|
在`main.ts`中,我们现在会注册一个`pcPhoneDetail`指令,而不再是组件。该指令是`PhoneDetail`组件的一个降级版。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-detail', 'app/main.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-detail', 'app/main.ts')
|
||||||
@ -2070,7 +2070,7 @@ code-example(format="").
|
|||||||
|
|
||||||
We should put this `<phonecat-app>` element in the HTML so that the root component
|
We should put this `<phonecat-app>` element in the HTML so that the root component
|
||||||
has something to attach to. It replaces the old Angular 1 `ng-view` directive:
|
has something to attach to. It replaces the old Angular 1 `ng-view` directive:
|
||||||
|
|
||||||
我们还要把这个`<pc-app>`元素放进HTML中,以便这个根组件可以附加上去。它代替了Angular 1中原来的`ng-view`指令:
|
我们还要把这个`<pc-app>`元素放进HTML中,以便这个根组件可以附加上去。它代替了Angular 1中原来的`ng-view`指令:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/ts/index.html', 'appcomponent', 'index.html')
|
+makeExample('upgrade-phonecat-3-final/ts/index.html', 'appcomponent', 'index.html')
|
||||||
@ -2091,7 +2091,7 @@ code-example(format="").
|
|||||||
With that, we're ready to switch the bootstrap method of the application from that
|
With that, we're ready to switch the bootstrap method of the application from that
|
||||||
of the `UpgradeAdapter` to the main Angular 2 `bootstrap`. Let's import it together
|
of the `UpgradeAdapter` to the main Angular 2 `bootstrap`. Let's import it together
|
||||||
with the router, the new app component, and everything else in `main.ts`
|
with the router, the new app component, and everything else in `main.ts`
|
||||||
|
|
||||||
使用它,我们就可以把来自`UpgradeAdapter`中的`bootstrap`方法切换到Angular 2自己的`bootstrap`了。
|
使用它,我们就可以把来自`UpgradeAdapter`中的`bootstrap`方法切换到Angular 2自己的`bootstrap`了。
|
||||||
通过路由器和`main.ts`中新的应用组件,我们把它们导入到一起:
|
通过路由器和`main.ts`中新的应用组件,我们把它们导入到一起:
|
||||||
|
|
||||||
@ -2117,12 +2117,12 @@ code-example(format="").
|
|||||||
We also configure a couple of things for the router here so that the application
|
We also configure a couple of things for the router here so that the application
|
||||||
URL paths match exactly those we had in the Angular 1 app: We want the
|
URL paths match exactly those we had in the Angular 1 app: We want the
|
||||||
hash location strategy with the `!` prefix: `#!/phones`.
|
hash location strategy with the `!` prefix: `#!/phones`.
|
||||||
|
|
||||||
这里我们还为路由器配置了一组东西,以便应用的URL路径和我们在Angular 1应用中用过的完全匹配:
|
这里我们还为路由器配置了一组东西,以便应用的URL路径和我们在Angular 1应用中用过的完全匹配:
|
||||||
我们希望hash地址策略使用`!`前缀:`#!/phones`。
|
我们希望hash地址策略使用`!`前缀:`#!/phones`。
|
||||||
|
|
||||||
At this point we are running a pure Angular 2 application!
|
At this point we are running a pure Angular 2 application!
|
||||||
|
|
||||||
此时,我们就在运行一个纯Angular 2应用了。
|
此时,我们就在运行一个纯Angular 2应用了。
|
||||||
|
|
||||||
But there's actually one more cool thing we can do with the new router.
|
But there's actually one more cool thing we can do with the new router.
|
||||||
@ -2139,14 +2139,14 @@ code-example(format="").
|
|||||||
|
|
||||||
:marked
|
:marked
|
||||||
For this to work the directive just needs to be declared in the component:
|
For this to work the directive just needs to be declared in the component:
|
||||||
|
|
||||||
要让该指令能够工作,我们只需要把它在组件中声明一下:
|
要让该指令能够工作,我们只需要把它在组件中声明一下:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts', 'top')
|
+makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts', 'top')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
## Saying Goodbye to Angular 1
|
## Saying Goodbye to Angular 1
|
||||||
## 再见,Angular
|
## 再见,Angular 1
|
||||||
|
|
||||||
It is time to take off the training wheels and let our application begin
|
It is time to take off the training wheels and let our application begin
|
||||||
its new life as a pure, shiny Angular 2 app. The remaining tasks all have to
|
its new life as a pure, shiny Angular 2 app. The remaining tasks all have to
|
||||||
@ -2157,11 +2157,11 @@ code-example(format="").
|
|||||||
|
|
||||||
If you haven't already, remove all references to the `UpgradeAdapter` from `main.ts`.
|
If you haven't already, remove all references to the `UpgradeAdapter` from `main.ts`.
|
||||||
Also remove the Angular 1 bootstrap code.
|
Also remove the Angular 1 bootstrap code.
|
||||||
|
|
||||||
请从`main.ts`中移除所有到`UpgradeAdapter`的引用,并移除Angular 1的引导代码。
|
请从`main.ts`中移除所有到`UpgradeAdapter`的引用,并移除Angular 1的引导代码。
|
||||||
|
|
||||||
When you're done, this is what `main.ts` should look like:
|
When you're done, this is what `main.ts` should look like:
|
||||||
|
|
||||||
都完成了之后,`main.ts`看起来应该像这样:
|
都完成了之后,`main.ts`看起来应该像这样:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/ts/app/main.ts', null, 'app/main.ts')
|
+makeExample('upgrade-phonecat-3-final/ts/app/main.ts', null, 'app/main.ts')
|
||||||
@ -2169,7 +2169,7 @@ code-example(format="").
|
|||||||
:marked
|
:marked
|
||||||
You may also completely remove the following files. They are Angular 1
|
You may also completely remove the following files. They are Angular 1
|
||||||
module configuration files and not needed in Angular 2:
|
module configuration files and not needed in Angular 2:
|
||||||
|
|
||||||
我们还要完全移除了下列文件。它们是Angular 1的模块配置文件和类型定义文件,在Angular 2中不需要了:
|
我们还要完全移除了下列文件。它们是Angular 1的模块配置文件和类型定义文件,在Angular 2中不需要了:
|
||||||
|
|
||||||
* `app/app.module.ts`
|
* `app/app.module.ts`
|
||||||
@ -2196,7 +2196,7 @@ code-example(format="").
|
|||||||
Finally, from `index.html`, remove all references to
|
Finally, from `index.html`, remove all references to
|
||||||
Angular 1 scripts, the Angular 2 upgrade module, and jQuery. When we're done,
|
Angular 1 scripts, the Angular 2 upgrade module, and jQuery. When we're done,
|
||||||
this is what it should look like:
|
this is what it should look like:
|
||||||
|
|
||||||
最后,从`index.html`和`karma.conf.js`中,移除所有到Angular 1脚本的引用,比如jQuery。
|
最后,从`index.html`和`karma.conf.js`中,移除所有到Angular 1脚本的引用,比如jQuery。
|
||||||
当这些全部做完时,`index.html`看起来应该是这样的:
|
当这些全部做完时,`index.html`看起来应该是这样的:
|
||||||
|
|
||||||
@ -2211,14 +2211,18 @@ code-example(format="").
|
|||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
# Appendix: Upgrading PhoneCat Tests
|
# Appendix: Upgrading PhoneCat Tests
|
||||||
|
|
||||||
# 附录:升级PhoneCat的测试
|
# 附录:升级PhoneCat的测试
|
||||||
|
|
||||||
Tests can not only be retained through an upgrade process, but they can also be
|
Tests can not only be retained through an upgrade process, but they can also be
|
||||||
used as a valuable safety measure when ensuring that the application does not
|
used as a valuable safety measure when ensuring that the application does not
|
||||||
break during the upgrade. E2E tests are especially useful for this purpose.
|
break during the upgrade. E2E tests are especially useful for this purpose.
|
||||||
|
|
||||||
|
测试不仅要在升级过程中被保留,它还是确保应用在升级过程中不会被破坏的一个安全指示器。
|
||||||
|
要达到这个目的,E2E测试尤其有用。
|
||||||
|
|
||||||
## E2E Tests
|
## E2E Tests
|
||||||
|
## E2E测试
|
||||||
|
|
||||||
The PhoneCat project has both E2E Protractor tests and some Karma unit tests in it.
|
The PhoneCat project has both E2E Protractor tests and some Karma unit tests in it.
|
||||||
Of these two, E2E tests can be dealt with much more easily: By definition,
|
Of these two, E2E tests can be dealt with much more easily: By definition,
|
||||||
@ -2229,17 +2233,32 @@ code-example(format="").
|
|||||||
test suite should keep passing with just minor modifications. This is because
|
test suite should keep passing with just minor modifications. This is because
|
||||||
we don't change how the application behaves from the user's point of view.
|
we don't change how the application behaves from the user's point of view.
|
||||||
|
|
||||||
|
PhoneCat项目中同时有基于Protractor的E2E测试和一些基于Karma的单元测试。
|
||||||
|
对这两者来说,E2E测试的转换要容易得多:根据定义,E2E测试通过与应用中显示的这些UI元素互动,从*外部*访问我们的应用来进行测试。
|
||||||
|
E2E测试实际上并不关心这些应用中各部件的内部结构。这也意味着,虽然我们已经修改了一点儿此应用程序,
|
||||||
|
但是E2E测试套件仍然应该能像以前一样全部通过。因为从用户的角度来说,我们并没有改变应用的行为。
|
||||||
|
|
||||||
During TypeScript conversion, there is nothing we have to do to keep E2E tests
|
During TypeScript conversion, there is nothing we have to do to keep E2E tests
|
||||||
working. It is only when we start to upgrade components and their template to Angular 2
|
working. It is only when we start to upgrade components and their template to Angular 2
|
||||||
that we need to make some changes. This is because the E2E tests have matchers
|
that we need to make some changes. This is because the E2E tests have matchers
|
||||||
that are specific to Angular 1. For PhoneCat we need to make the following changes
|
that are specific to Angular 1. For PhoneCat we need to make the following changes
|
||||||
in order to make things work with Angular 2:
|
in order to make things work with Angular 2:
|
||||||
|
|
||||||
|
在转成TypeScript期间,我们不用做什么就能让E2E测试正常工作。
|
||||||
|
只有当我们想做些修改而把组件及其模板升级到Angular 2时才需要做些处理。
|
||||||
|
这是因为E2E测试有一些匹配器是Angular 1中特有的。对于PhoneCat来说,为了让它能在Angular 2下工作,我们得做下列修改:
|
||||||
|
|
||||||
table
|
table
|
||||||
tr
|
tr
|
||||||
th Previous code
|
th
|
||||||
th New code
|
p Previous code
|
||||||
th Notes
|
p 老代码
|
||||||
|
th
|
||||||
|
p New code
|
||||||
|
p 新代码
|
||||||
|
th
|
||||||
|
p Notes
|
||||||
|
p 说明
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
@ -2250,6 +2269,8 @@ table
|
|||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
The repeater matcher relies on Angular 1 `ng-repeat`
|
The repeater matcher relies on Angular 1 `ng-repeat`
|
||||||
|
|
||||||
|
repeater匹配器依赖于Angular 1中的`ng-repeat`
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
@ -2260,6 +2281,8 @@ table
|
|||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
The repeater matcher relies on Angular 1 `ng-repeat`
|
The repeater matcher relies on Angular 1 `ng-repeat`
|
||||||
|
|
||||||
|
repeater匹配器依赖于Angular 1中的`ng-repeat`
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
@ -2270,6 +2293,8 @@ table
|
|||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
The model matcher relies on Angular 1 `ng-model`
|
The model matcher relies on Angular 1 `ng-model`
|
||||||
|
|
||||||
|
model匹配器依赖于Angular 1中的`ng-model`
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
@ -2280,6 +2305,8 @@ table
|
|||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
The model matcher relies on Angular 1 `ng-model`
|
The model matcher relies on Angular 1 `ng-model`
|
||||||
|
|
||||||
|
model匹配器依赖于Angular 1中的`ng-model`
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
:marked
|
:marked
|
||||||
@ -2291,6 +2318,7 @@ table
|
|||||||
:marked
|
:marked
|
||||||
The binding matcher relies on Angular 1 data binding
|
The binding matcher relies on Angular 1 data binding
|
||||||
|
|
||||||
|
binding匹配器依赖于Angular 1的数据绑定
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
When the bootstrap method is switched from that of `UpgradeAdapter` to
|
When the bootstrap method is switched from that of `UpgradeAdapter` to
|
||||||
@ -2299,6 +2327,10 @@ table
|
|||||||
an Angular 1 app anymore, but instead it should find *Angular 2 apps* from
|
an Angular 1 app anymore, but instead it should find *Angular 2 apps* from
|
||||||
the page. The following change is then needed in `protractor-conf.js`:
|
the page. The following change is then needed in `protractor-conf.js`:
|
||||||
|
|
||||||
|
当引导方式从`UpgradeAdapter`切换到纯Angular 2的时,Angular 1就从页面中完全消失了。
|
||||||
|
此时,我们需要告诉Protractor,它不用再找Angular 1应用了,而是从页面中查找*Angular 2*应用。
|
||||||
|
于是在`protractor-conf.js`中做下列修改:
|
||||||
|
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
useAllAngular2AppRoots: true,
|
useAllAngular2AppRoots: true,
|
||||||
|
|
||||||
@ -2309,11 +2341,16 @@ code-example(format="").
|
|||||||
that use WebDriver's generic URL APIs instead. The first of these is
|
that use WebDriver's generic URL APIs instead. The first of these is
|
||||||
the redirection spec:
|
the redirection spec:
|
||||||
|
|
||||||
|
同样,我们的测试代码中有两个Protractor API调用内部使用了`$location`。该服务没有了,
|
||||||
|
我们就得把这些调用用一个WebDriver的通用URL API代替。第一个API是“重定向(redirect)”规约:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/e2e-spec.js', 'redirect', 'e2e-tests/scenarios.js')
|
+makeExample('upgrade-phonecat-3-final/e2e-spec.js', 'redirect', 'e2e-tests/scenarios.js')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
And the second is the phone links spec:
|
And the second is the phone links spec:
|
||||||
|
|
||||||
|
第二个是“电话链接(phone links)”规约:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/e2e-spec.js', 'links', 'e2e-tests/scenarios.js')
|
+makeExample('upgrade-phonecat-3-final/e2e-spec.js', 'links', 'e2e-tests/scenarios.js')
|
||||||
|
|
||||||
|
|
||||||
@ -2321,17 +2358,27 @@ code-example(format="").
|
|||||||
:marked
|
:marked
|
||||||
## Unit Tests
|
## Unit Tests
|
||||||
|
|
||||||
|
## 单元测试
|
||||||
|
|
||||||
For unit tests, on the other hand, more conversion work is needed. Effectively
|
For unit tests, on the other hand, more conversion work is needed. Effectively
|
||||||
they need to be *upgraded* along with the production code.
|
they need to be *upgraded* along with the production code.
|
||||||
|
|
||||||
|
另一方面,对于单元测试来说,需要更多的转化工作。实际上,它们需要随着产品代码一起升级。
|
||||||
|
|
||||||
During TypeScript conversion no changes are strictly necessary. But it may be
|
During TypeScript conversion no changes are strictly necessary. But it may be
|
||||||
a good idea to convert the unit test code into TypeScript as well, as the same
|
a good idea to convert the unit test code into TypeScript as well, as the same
|
||||||
benefits we from TypeScript in production code also applies to tests.
|
benefits we from TypeScript in production code also applies to tests.
|
||||||
|
|
||||||
|
在转成TypeScript期间,严格来讲没有什么改动是必须的。但把单元测试代码转成TypeScript仍然是个好主意,
|
||||||
|
产品代码从TypeScript中获得的那些增益也同样适用于测试代码。
|
||||||
|
|
||||||
For instance, in the phone detail component spec we can use not only ES2015
|
For instance, in the phone detail component spec we can use not only ES2015
|
||||||
features like arrow functions and block-scoped variables, but also type
|
features like arrow functions and block-scoped variables, but also type
|
||||||
definitions for some of the Angular 1 services we're consuming:
|
definitions for some of the Angular 1 services we're consuming:
|
||||||
|
|
||||||
|
比如,在这个电话详情组件的规约中,我们不仅用到了ES2015中的箭头函数和块作用域变量这些特性,还为所用的一些
|
||||||
|
Angular 1服务提供了类型定义。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-1-typescript/ts/app/phone-detail/phone-detail.component.spec.ts', null, 'app/phone-detail/phone-detail.component.spec.ts')
|
+makeExample('upgrade-phonecat-1-typescript/ts/app/phone-detail/phone-detail.component.spec.ts', null, 'app/phone-detail/phone-detail.component.spec.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -2339,15 +2386,22 @@ code-example(format="").
|
|||||||
are needed for Karma. We need to let SystemJS load all the new Angular 2 code,
|
are needed for Karma. We need to let SystemJS load all the new Angular 2 code,
|
||||||
which can be done with the following kind of shim file:
|
which can be done with the following kind of shim file:
|
||||||
|
|
||||||
|
一旦我们开始了升级过程并引入了SystemJS,还需要对Karma进行配置修改。
|
||||||
|
我们需要让SystemJS加载所有的Angular 2新代码,
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/karma-test-shim.1.js', null, 'karma-test-shim.js')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/karma-test-shim.1.js', null, 'karma-test-shim.js')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The shim first loads the SystemJS configuration, then Angular 2's test support libraries,
|
The shim first loads the SystemJS configuration, then Angular 2's test support libraries,
|
||||||
and then the application's spec files themselves.
|
and then the application's spec files themselves.
|
||||||
|
|
||||||
|
这个shim文件首先加载了SystemJS的配置,然后是Angular 2的测试支持库,然后是应用本身的规约文件。
|
||||||
|
|
||||||
Karma configuration should then be changed so that it uses the application root dir
|
Karma configuration should then be changed so that it uses the application root dir
|
||||||
as the base directory, instead of `app`.
|
as the base directory, instead of `app`.
|
||||||
|
|
||||||
|
然后需要修改Karma配置,来让它使用本应用的根目录作为基础目录(base directory),而不是`app`。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js', 'basepath', 'karma.conf.js')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js', 'basepath', 'karma.conf.js')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -2355,12 +2409,17 @@ code-example(format="").
|
|||||||
for loading application files so that they are *not* included to the page by Karma. We'll let
|
for loading application files so that they are *not* included to the page by Karma. We'll let
|
||||||
the shim and SystemJS load them.
|
the shim and SystemJS load them.
|
||||||
|
|
||||||
|
一旦这些完成了,我们就能加载SystemJS和其它依赖,并切换配置文件来加载那些应用文件,而*不用*在Karma页面中包含它们。
|
||||||
|
我们要让这个shim文件和SystemJS去加载它们。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js', 'files', 'karma.conf.js')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js', 'files', 'karma.conf.js')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Since the HTML templates of Angular 2 components will be loaded as well, we need to help
|
Since the HTML templates of Angular 2 components will be loaded as well, we need to help
|
||||||
Karma out a bit so that it can route them to the right paths:
|
Karma out a bit so that it can route them to the right paths:
|
||||||
|
|
||||||
|
由于Angular 2组件中的HTML模板也同样要被加载,所以我们得帮Karma一把,帮它在正确的路径下找到这些模板:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js', 'html', 'karma.conf.js')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js', 'html', 'karma.conf.js')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -2368,18 +2427,24 @@ code-example(format="").
|
|||||||
counterparts are switched. The specs for the checkmark pipe are probably the most straightforward,
|
counterparts are switched. The specs for the checkmark pipe are probably the most straightforward,
|
||||||
as the pipe has no dependencies:
|
as the pipe has no dependencies:
|
||||||
|
|
||||||
|
如果产品代码被切换到了Angular 2,单元测试文件本身也需要切换过来。对勾儿(checkmark)管道的规约可能是最简单的,因为它没有任何依赖:
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/checkmark/checkmark.pipe.spec.ts', null, 'app/core/checkmark/checkmark.pipe.spec.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/checkmark/checkmark.pipe.spec.ts', null, 'app/core/checkmark/checkmark.pipe.spec.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The unit test for the phone service is a bit more involved. We need to switch from the mocked-out
|
The unit test for the phone service is a bit more involved. We need to switch from the mocked-out
|
||||||
Angular 1 `$httpBackend` to a mocked-out Angular 2 Http backend.
|
Angular 1 `$httpBackend` to a mocked-out Angular 2 Http backend.
|
||||||
|
|
||||||
|
`Phone`服务的测试会牵扯到一点别的。我们需要把模拟版的Angular 1 `$httpBackend`服务切换到模拟板的Angular 2 Http后端。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/phone/phone.service.spec.ts', null, 'app/core/phone/phone.service.spec.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/phone/phone.service.spec.ts', null, 'app/core/phone/phone.service.spec.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
For the component specs we can mock out the `Phone` service itself, and have it provide
|
For the component specs we can mock out the `Phone` service itself, and have it provide
|
||||||
canned phone data. We use Angular's component unit testing APIs for both components.
|
canned phone data. We use Angular's component unit testing APIs for both components.
|
||||||
|
|
||||||
|
对于组件的规约,我们可以模拟出`Phone`服务本身,并且让它提供电话的数据。我们可以对这些组件使用Angular的组件单元测试API。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.spec.ts', null, 'app/phone-detail/phone-detail.component.spec.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.spec.ts', null, 'app/phone-detail/phone-detail.component.spec.ts')
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.spec.ts', null, 'app/phone-list/phone-list.component.spec.ts')
|
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.spec.ts', null, 'app/phone-list/phone-list.component.spec.ts')
|
||||||
@ -2390,10 +2455,15 @@ code-example(format="").
|
|||||||
router. For the details component we need to provide an Angular 2 `RouteParams` object
|
router. For the details component we need to provide an Angular 2 `RouteParams` object
|
||||||
instead of using the Angular 1 `$routeParams`.
|
instead of using the Angular 1 `$routeParams`.
|
||||||
|
|
||||||
|
最后,当我们切换到Angular 2路由时,我们需要重新过一遍这些组件测试。对详情组件来说,我们需要提供一个Angular 2的
|
||||||
|
`RouteParams`对象,而不再用Angular 1的`$routeParams`。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts', 'routeparams', 'app/phone-detail/phone-detail.component.spec.ts')
|
+makeExample('upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts', 'routeparams', 'app/phone-detail/phone-detail.component.spec.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
And for the phone list component we need to set up a few things for the router itself so that
|
And for the phone list component we need to set up a few things for the router itself so that
|
||||||
the route link directive will work.
|
the route link directive will work.
|
||||||
|
|
||||||
|
对于电话列表组件来说,我们需要为路由器本身略作设置,以便它的路由链接(`routerLink`)指令能够正常工作。
|
||||||
|
|
||||||
+makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.spec.ts', 'routestuff', 'app/phone-list/phone-list.component.spec.ts')
|
+makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.spec.ts', 'routestuff', 'app/phone-list/phone-list.component.spec.ts')
|
||||||
|
@ -11,7 +11,7 @@ include ../_util-fns
|
|||||||
It's an excellent alternative to the *SystemJS* approach we use throughout the documentation.
|
It's an excellent alternative to the *SystemJS* approach we use throughout the documentation.
|
||||||
In this guide we get a taste of Webpack and how to use it with Angular 2 applications.
|
In this guide we get a taste of Webpack and how to use it with Angular 2 applications.
|
||||||
|
|
||||||
这是我们在文档中到处使用的这个*SystemJS*的一个卓越替代品。这篇指南会带我们尝尝Webpack的滋味,并学习如何在Angular 2程序中使用它。
|
这是我们在文档中到处使用的这个*SystemJS*的一个优秀替代品。这篇指南会带我们尝尝Webpack的滋味,并学习如何在Angular 2程序中使用它。
|
||||||
|
|
||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
1. Jasmine Testing 101
|
1. Jasmine Testing 101
|
||||||
|
|
||||||
1. Jasmine测试101
|
1. Jasmine测试简介
|
||||||
|
|
||||||
- setup to run Jasmine tests in the browser
|
- setup to run Jasmine tests in the browser
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ figure.image-display
|
|||||||
|
|
||||||
Congratulations … you’ve completed Jasmine testing 101.
|
Congratulations … you’ve completed Jasmine testing 101.
|
||||||
|
|
||||||
恭喜...你完成了Jasmine测试101。
|
恭喜...你完成了Jasmine测试简介。
|
||||||
|
|
||||||
Now that we’re familiar with Jasmine on its own, we’re ready to test an application.
|
Now that we’re familiar with Jasmine on its own, we’re ready to test an application.
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
box-shadow: 3px 0px 6px rgba($coal, .3);
|
box-shadow: 3px 0px 6px rgba($coal, .3);
|
||||||
width: 232px;
|
width: 232px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
height: calc(100vh - 56px);
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
@media handheld and (max-width: $phone-breakpoint),
|
@media handheld and (max-width: $phone-breakpoint),
|
||||||
@ -149,7 +148,10 @@
|
|||||||
screen and (max-device-width: $phone-breakpoint),
|
screen and (max-device-width: $phone-breakpoint),
|
||||||
screen and (max-width: $tablet-breakpoint) {
|
screen and (max-width: $tablet-breakpoint) {
|
||||||
display: none;
|
display: none;
|
||||||
//max-height: ($phone-breakpoint * 0.60);
|
&.is-visible {
|
||||||
|
height: calc(100vh - 56px - 48px);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FLAT NAV (.nav)
|
// FLAT NAV (.nav)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user