angular-cn/public/docs/ts/latest/guide/style-guide.jade

2708 lines
89 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

include ../_util-fns
:marked
Welcome to the Angular 2 Style Guide
欢迎光临Angular 2风格指南
## Purpose
## 目的
If you are looking for an opinionated style guide for syntax, conventions, and structuring Angular applications, then step right in.
如果你在寻找一份关于语法、约定和Angular应用程序的组织结构的风格指南那你就来对了。
The purpose of this style guide is to provide guidance on building Angular applications by showing the conventions we use and, more importantly, why we choose them.
本指南的目的是为开发Angular应用程序提供指导原则展示我们所遵循的约定更重要的是解释我们为什么要选择这些约定。
.l-main-section
:marked
## Style Vocabulary
## 风格词汇
Each guideline describes either a good or bad practice, and all have a consistent presentation.
每个指导原则都会描述好的或者坏的做法,所有指导原则都相互呼应,保持一致。
The wording of each guideline indicates how strong the recommendation is.
指导原则中使用的词汇表明我们推荐的强度。
.s-rule.do
:marked
**Do** is one that should always be followed. _Always_ might be a bit too strong of a word. Guidelines that literally should always be followed are extremely rare. On the other hand, we need a really unusual case for breaking a *Do* guideline.
**坚持**意味着总是应该遵循的约定。_总是_可能有点太强。应该_总是_遵循的指导原则非常少见。但是只有遇到非常不寻常的情况才能打破*坚持*的原则。
.s-rule.consider
:marked
**Consider** guidelines should generally be followed.
**考虑**标志着通常应该遵循的指导原则。
If you fully understand the meaning behind the guideline and have a good reason to deviate, then do so. Please strive to be consistent.
如果你能完全理解指导原则背后的含义,并且很好的理由打破它,那就可以打破该指导原则。但是请保持一致。
.s-rule.avoid
:marked
**Avoid** indicates something we should almost never do. Code examples to *avoid* have an unmistakeable red header.
**避免**标志着我们决不应该做的事。需要*避免*的代码范例会有不会被忽视的红色标题。
.l-main-section
:marked
## File Structure Conventions
## 文件结构约定
Some code examples display a file that has one or more similarly named companion files. (e.g. hero.component.ts and hero.component.html).
在一些代码例子中,有的文件拥有一个或多个相似名字的伴随文件。(比如hero.component.ts和hero.component.html)。
The guideline will use the shortcut `hero.component.ts|html|css|spec` to represent those various files. Using this shortcut makes this guide's file structures easier to read and more terse.
本指南将会使用像`hero.component.ts|html|css|spec`的简写来表示上面描述的多个文件,目的是保持本指南的简洁性,增加文件结构描述时的可读性。
.l-main-section
a(id='toc')
:marked
## Table of Contents
## 目录
1. [Single Responsibility](#single-responsibility)
1. [单一职责](#single-responsibility)
1. [Naming](#naming)
1. [命名约定](#naming)
1. [Coding Conventions](#coding-conventions)
1. [代码约定](#coding-conventions)
1. [Application Structure](#application-structure)
1. [应用程序结构](#application-structure)
1. [Components](#components)
1. [组件](#components)
1. [Directives](#directives)
1. [指令](#directives)
1. [Services](#services)
1. [服务](#services)
1. [Data Services](#data-services)
1. [数据服务](#data-services)
1. [Lifecycle Hooks](#lifecycle-hooks)
1. [生命周期钩子](#lifecycle-hooks)
1. [Routing](#routing)
1. [路由](#routing)
1. [Appendix](#appendix)
1. [附录](#appendix)
.l-main-section
:marked
## Single Responsibility
## 单一职责
We apply the [Single Responsibility Principle](https:\/\/en.wikipedia.org/wiki/Single_responsibility_principle) to all Components, Services, and other symbols we create.
This helps make our app cleaner, easier to read and maintain, and more testable.
我们遵循[单一职责原则](https:\/\/en.wikipedia.org/wiki/Single_responsibility_principle)来创建的所有组件、服务和其它标志等。这样能帮助我们把应用程序弄的干净整洁,易于阅读、维护和测试。
### <a id="01-01"></a>Rule of One
### <a id="01-01"></a>单一法则
#### <a href="#01-01">Style 01-01</a>
#### <a href="#01-01">风格 01-01</a>
.s-rule.do
:marked
**Do** define one thing (e.g. service or component) per file.
**坚持**每个文件只定义一样东西(比如服务或者组件)。
.s-rule.consider
:marked
**Consider** limiting files to 400 lines of code.
**考虑**把文件大小限制在400行代码以内。
.s-why
:marked
**Why?** One component per file makes it far easier to read, maintain, and avoid collisions with teams in source control.
**为何?**单组件文件非常容易阅读、维护,并能防止在版本控制系统里与团队冲突。
.s-why
:marked
**Why?** One component per file avoids hidden bugs that often arise when combining components in a file where they may share variables, create unwanted closures, or unwanted coupling with dependencies.
**为何?**单组件文件可以防止一些隐蔽的程序缺陷,当把多个组件合写在同一个文件中时,可能造成共享变量、创建意外的闭包,或者与依赖之间产生意外耦合等情况。
.s-why.s-why-last
:marked
**Why?** A single component can be the default export for its file which facilitates lazy loading with the Component Router.
**为何?**单独的组件通常是该文件默认的输出,这样就可以利用组件路由器实现按需加载。
:marked
The key is to make the code more reusable, easier to read, and less mistake prone.
最关键的是,可以增强代码可重用性和阅读性,减少出错的可能性。
The following *negative* example defines the `AppComponent`, bootstraps the app, defines the `Hero` model object, and loads heroes from the server ... all in the same file. *Don't do this*.
下面的*负面*例子定义了`AppComponent`,该文件引导了应用程序,定义了`Hero`模型对象,并且从服务器加载了英雄 ... 所有都在发生在同一个文件。 *不要这么做*。
+makeExample('style-guide/ts/01-01/app/heroes/hero.component.avoid.ts', '', 'app/heroes/hero.component.ts')(avoid=1)
:marked
Better to redistribute the component and supporting activities into their own dedicated files.
将组件及其支撑部件重新分配到独立的文件中会更好。
+makeTabs(
`style-guide/ts/01-01/main.ts,
style-guide/ts/01-01/app/app.component.ts,
style-guide/ts/01-01/app/heroes/heroes.component.ts,
style-guide/ts/01-01/app/heroes/shared/hero.service.ts,
style-guide/ts/01-01/app/heroes/shared/hero.model.ts,
style-guide/ts/01-01/app/heroes/shared/mock-heroes.ts`,
'',
`main.ts,
app/app.component.ts,
app/heroes/heroes.component.ts,
app/heroes/shared/hero.service.ts,
app/heroes/shared/hero.model.ts,
app/heroes/shared/mock-heroes.ts`)
:marked
As the app grows, this rule becomes even more important.
随着应用程序的成长,本法则会变得越来越重要。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
.s-rule.do
### <a id="01-02"></a>Small Functions
### <a id="01-02"></a>小函数
#### <a href="#01-02">Style 01-02</a>
#### <a href="#01-02">风格01-02</a>
:marked
**Do** define small functions
**坚持**定义小函数
.s-rule.consider
:marked
**Consider** limiting to no more than 75 lines.
**考虑**限制在75行之内
.s-why
:marked
**Why?** Small functions are easier to test, especially when they do one thing and serve one purpose.
**为何?**小函数更易于测试,特别是当它们只做一件事,只为一个目的服务的时候。
.s-why
:marked
**Why?** Small functions promote reuse.
**为何?**小函数促进了代码的重用。
.s-why
:marked
**Why?** Small functions are easier to read.
**为何?**小函数更加易于阅读。
.s-why
:marked
**Why?** Small functions are easier to maintain.
**为何?**小函数更加易于维护。
.s-why.s-why-last
:marked
**Why?** Small functions help avoid hidden bugs that come with large functions that share variables with external scope, create unwanted closures, or unwanted coupling with dependencies.
**为何?**小函数帮助避免一些大函数容易产生的那些与外界共享变量、创建意外的闭包或与依赖之间产生意外耦合等隐蔽的错误。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Naming
## 命名约定
Naming conventions are hugely important to maintainability and readability. This guide recommends naming conventions for the file name and the symbol name.
命名约定对维护性和可读性非常重要。本指南为文件和标志命名推荐了一套命名约定。
.l-main-section
:marked
### <a id="02-01"></a>General Naming Guidelines
### <a id="02-01"></a>总体命名知道原则
#### <a href="#02-01">Style 02-01</a>
#### <a href="#02-01">风格02-01</a>
.s-rule.do
:marked
**Do** use consistent names for all symbols.
**坚持**为所有符号使用一致的命名规则。
.s-rule.do
:marked
**Do** follow a pattern that describes the symbol's feature then its type. The recommended pattern is `feature.type.ts`.
**坚持**遵循同一个模式来描述符号的特性和类型。推荐的模式为`feature.type.ts`。
.s-why
:marked
**Why?** Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important.
Consistency across a company provides tremendous efficiency.
**为何?**命名约定提供了一致的方法来帮助我们一眼锁定内容。在整个项目内保持一致性是至关重要的。在团队内保持一致性也很重要。在公司内部保持一致性可以大幅提高效率。
.s-why
:marked
**Why?** The naming conventions should simply help us find our code faster and make it easier to understand.
**为何?**命名约定最直接的目的是:帮我们快速找到代码并让它们更容易理解。
.s-why.s-why-last
:marked
**Why?** Names of folders and files should clearly convey their intent. For example, `app/heroes/hero-list.component.ts` may contain a component that manages a list of heroes.
**为何?**目录和文件的名字应该清楚的说明它们的用途。比如`app/heroes/hero-list.component.ts`包含了一个用来维护英雄列表的组件。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-02"></a>Separate File Names with Dots and Dashes
### <a id="02-02"></a>使用点和横杠来分隔文件名
#### <a href="#02-02">Style 02-02</a>
#### <a href="#02-02">风格02-02</a>
.s-rule.do
:marked
**Do** use dashes to separate words in the descriptive name.
**坚持** 在描述性名字里面,使用横杠来分隔单词。
.s-rule.do
:marked
**Do** use dots to separate the descriptive name from the type.
**坚持**使用点来分隔描述性名字和类型名。
.s-rule.do
:marked
**Do** use consistent type names for all components following a pattern that describes the component's feature then its type. A recommended pattern is `feature.type.ts`.
**坚持**对所有组件使用一致的类型命名规则,遵循这个模式:先描述组件的特性,再描述它的类型。推荐的模式为`feature.type.ts`。
.s-rule.do
:marked
**Do** use conventional type names including `.service`, `.component`, `.pipe`.
Invent additional type names if you must but take care not to create too many.
**坚持**使用惯用的后缀来描述类型,比如`*.service`、`*.component`、`*.pipe`。
创建额外的类型名字,但你必须注意不要创建太多。
.s-why
:marked
**Why?** Type names provide a consistent way to quickly identify what is in the file.
**为何?**类型名字提供一致的方法来快速的识别文件是什么。
.s-why
:marked
**Why?** Make it easy to find a specific file type using an editor or IDE's fuzzy search techniques.
**为何?** 可以让我们利用编辑器或者IDE的模糊搜索功能很容易的找到特定文件。
.s-why
:marked
**Why?** Unabbreviated type names such as `.service` are descriptive and unambiguous.
Abbreviations such as `.srv`, `.svc`, and `.serv` can be confusing.
**为何?** 没有被简写的类型名字比如`.service`很有描述性,不含糊。
简写可能造成混淆,比如`.srv`, `.svc`, 和 `.serv`。
.s-why.s-why-last
:marked
**Why?** Provides pattern matching for any automated tasks.
**为何?**与自动化任务的模式匹配。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-03"></a>Components and Directives
### <a id="02-03"></a>组件与指令命名
#### <a href="#02-03">Style 02-03</a>
#### <a href="#02-03">风格02-03</a>
.s-rule.do
:marked
**Do** use consistent names for all assets named after what they represent.
**坚持**为所有东西使用一致的命名约定:以它们所代表的东西命名。
.s-rule.do
:marked
**Do** use upper camel case for symbols. Match the name of the symbol to the naming of the file.
**坚持**使用大写驼峰命名法来命名所有符号(类)。保持符号的名字与它所在的文件名字相同。
.s-rule.do
:marked
**Do** append the symbol name with the suffix that it represents.
**坚持**把符号的类型(比如组件、服务、指令等)附加到符号名的后面。
.s-why
:marked
**Why?** Provides a consistent way to quickly identify and reference assets.
**为何?**提供前后一致的方法迅速辨识和引用东西。
.s-why
:marked
**Why?** Upper camel case is conventional for identifying objects that can be instantiated using a constructor.
**为何?**大写驼峰命名法约定用来辨识出那些可通过构造函数来实例化的对象。
.s-why.s-why-last
:marked
**Why?** The `Component` suffix is more commonly used and is more explicitly descriptive.
**为何?**`Component`后缀是常见的用法,它具有精准的描述性。
- var top="vertical-align:top"
table(width="100%")
col(width="50%")
col(width="50%")
tr
th
p Symbol Name
p 符号名
th
p File Name
p 文件名
tr(style=top)
td
code-example.
@Component({ ... })
export class AppComponent {}
td
:marked
app.component.ts
tr(style=top)
td
code-example.
@Component({ ... })
export class HeroesComponent
td
:marked
heroes.component.ts
tr(style=top)
td
code-example.
@Component({ ... })
export class HeroListComponent
td
:marked
hero-list.component.ts
tr(style=top)
td
code-example.
@Component({ ... })
export class HeroDetailComponent
td
:marked
hero-detail.component.ts
tr(style=top)
td
code-example.
@Directive({ ... })
export class ValidationDirective
td
:marked
validation.directive.ts
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-04"></a>Service Names
### <a id="02-04"></a>服务名
#### <a href="#02-04">Style 02-04</a>
#### <a href="#02-04">风格02-04</a>
.s-rule.do
:marked
**Do** use consistent names for all services named after their feature.
**坚持**使用前后一致的命名规则来命名服务,以它们的特性来命名。
.s-rule.do
:marked
**Do** use upper camel case for services.
**坚持**使用大写驼峰命名法来命名服务。
.s-rule.do
:marked
**Do** suffix services with `Service` when it is not clear what they are (e.g. when they are nouns).
**坚持**当不能从它们的名字里清楚的看出它们是什么的时候(比如它们的名字是名词时),添加`Service`后缀。
.s-why
:marked
**Why?** Provides a consistent way to quickly identify and reference services.
**为何?**提供前后一致的方法来快速识别和引用服务。
.s-why
:marked
**Why?** Clear service names such as `Logger` do not require a suffix.
**为何?**清楚的服务名,比如`Logger`不需要后缀。
.s-why.s-why-last
:marked
**Why?** Service names such as `Credit` are nouns and require a suffix and should be named with a suffix when it is not obvious if it is a service or something else.
**为何?**如果服务名字是名词时,比如`Credit`,需要一个后缀。当名字不能很明显的标示出它是服务还是其它东西的时候,应该添加后缀。
- var top="vertical-align:top"
table(width="100%")
col(width="50%")
col(width="50%")
tr
th
p Symbol Name
p 符号名
th
p File Name
p 文件名
tr(style=top)
td
code-example.
@Injectable()
export class HeroDataService {}
td
:marked
hero-data.service.ts
tr(style=top)
td
code-example.
@Injectable()
export class CreditService {}
td
:marked
credit.service.ts
tr(style=top)
td
code-example.
@Injectable()
export class Logger {}
td
:marked
logger.service.ts
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-05"></a>Bootstrapping
### <a id="02-05"></a>引导
#### <a href="#02-05">Style 02-05</a>
#### <a href="#02-05">风格02-05</a>
.s-rule.do
:marked
**Do** put bootstrapping and platform logic for the app in a file named `main.ts`.
**坚持**把应用的引导程序和平台相关的逻辑放到名为`main.ts`的文件里。
.s-rule.avoid
:marked
**Avoid** putting app logic in the `main.ts`. Instead consider placing it in a Component or Service.
**避免**把应用逻辑放到`main.ts`里。考虑把它放到组件或服务里面。
.s-why
:marked
**Why?** Follows a consistent convention for the startup logic of an app.
**为何?**遵循前后一致的约定来处理应用的启动逻辑。
.s-why.s-why-last
:marked
**Why?** Follows a familiar convention from other technology platforms.
**为何?**这是从其它技术平台借鉴的一个常用约定。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-06"></a>Directive Selectors
### <a id="02-06"></a>指令的选择器
#### <a href="#02-06">Style 02-06</a>
#### <a href="#02-06">风格02-06</a>
.s-rule.do
:marked
**Do** Use lower camel case for naming the selectors of our directives.
**坚持**使用小驼峰命名法来命名指令的选择器。
.s-why
:marked
**Why?** Keeps the names of the properties defined in the directives that are bound to the view consistent with the attribute names.
**为何?**保持指令里定义的属性名字与它们绑定的视图HTML属性名字一致。
.s-why.s-why-last
:marked
**Why?** The Angular 2 HTML parser is case sensitive and will recognize lower camel case.
**为何?**Angular 2 HTML解析器是大小写敏感的它识别小写驼峰写法。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-07"></a>Custom Prefix for Components
### <a id="02-07"></a>为组件自定义前缀
#### <a href="#02-07">Style 02-07</a>
#### <a href="#02-07">风格02-07</a>
.s-rule.do
:marked
**Do** use a custom prefix for the selector of our components. For example, the prefix `toh` represents from **T**our **o**f **H**eroes and the prefix `admin` represents an admin feature area.
**坚持**为组件的选择器使用自定义前缀。比如,前缀`tod`是从**T**our **o**f **H**eros来的前缀`admin`代表了admin的特性区域。
.s-rule.do
:marked
**Do** use a prefix that identifies the feature area or the app itself.
**坚持**使用前缀来识别特性区域或者应用程序本身。
.s-why
:marked
**Why?** Prevents name collisions.
**为何?**防止名字冲突。
.s-why
:marked
**Why?** Makes it easier to promote and share our feature in other apps.
**为何?**把我们的代码推广和共享到其它应用中会更容易。
.s-why.s-why-last
:marked
**Why?** Our Components and elements are easily identified.
**为何?**我们组件和元素更容易被识别。
+makeExample('style-guide/ts/02-07/app/heroes/hero.component.avoid.ts', 'example', 'app/heroes/hero.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/02-07/app/users/users.component.avoid.ts', 'example', 'app/users/users.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/02-07/app/heroes/hero.component.ts', 'example', 'app/heroes/hero.component.ts')
:marked
+makeExample('style-guide/ts/02-07/app/users/users.component.ts', 'example', 'app/users/users.component.ts')
:marked
:marked
### <a id="02-08"></a>Custom Prefix for Directives
### <a id="02-08"></a>为指令添加自定义前缀
#### <a href="#02-08">Style 02-08</a>
#### <a href="#02-08">风格02-08</a>
.s-rule.do
:marked
**Do** use a custom prefix for the selector of our directives (for instance below we use the prefix `toh` from **T**our **o**f **H**eroes).
**坚持**为指令的选择器使用自定义的前缀(比如下面例子中,我们使用前缀`toh`,取自**T**our **o**f **H**eroes)。
.s-why
:marked
**Why?** Prevents name collisions.
**为何?**防止名字冲突。
.s-why.s-why-last
:marked
**Why?** Our Directives are easily identified.
**为何?**指令更加容易被识别。
+makeExample('style-guide/ts/02-08/app/shared/validate.directive.avoid.ts', 'example', 'app/shared/validate.directive.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/02-08/app/shared/validate.directive.ts', 'example', 'app/shared/validate.directive.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-09"></a>Pipe Names
### <a id="02-09"></a>管道名
#### <a href="#02-09">Style 02-09</a>
#### <a href="#02-09">风格02-09</a>
.s-rule.do
:marked
**Do** use consistent names for all pipes, named after their feature.
**坚持**为所有管道使用前后一致的命名约定,用它们的特性来命名。
.s-why.s-why-last
:marked
**Why?** Provides a consistent way to quickly identify and reference pipes.
**为何?**提供一致的方法快速识别和引用管道。
- var top="vertical-align:top"
table(width="100%")
col(width="50%")
col(width="50%")
tr
th
p Symbol Name
p 符号名
th
p File Name
p 文件名
tr(style=top)
td
code-example.
@Pipe({ name: 'ellipsis' })
export class EllipsisPipe implements PipeTransform { }
td
:marked
ellipsis.pipe.ts
tr(style=top)
td
code-example.
@Pipe({ name: 'initCaps' })
export class InitCapsPipe implements PipeTransform { }
td
:marked
init-caps.pipe.ts
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-10"></a>Unit Test File Names
### <a id="02-10"></a>单元测试文件名
#### <a href="#02-10">风格02-10</a>
.s-rule.do
:marked
**Do** name test specification files the same as the component they test.
**坚持**测试规范文件的名字应该和被测试的组件名字一样。
.s-rule.do
:marked
**Do** name test specification files with a suffix of `.spec`.
**坚持**测试配置文件命名应该跟随后缀`.spec`。
.s-why
:marked
**Why?** Provides a consistent way to quickly identify tests.
**为何?**提供一致的方法来快速识别测试。
.s-why.s-why-last
:marked
**Why?** Provides pattern matching for [karma](http://karma-runner.github.io/) or other test runners.
**为何?**提供一个与[karma](http://karma-runner.github.io/)或者其他测试运行器相配的命名模式。
:marked
- var top="vertical-align:top"
table(width="100%")
col(width="50%")
col(width="50%")
tr
th
p Symbol Name
p 符号名
th
p File Name
p 文件名
tr(style=top)
td
:marked
Components
组件
td
:marked
heroes.component.spec.ts
:marked
hero-list.component.spec.ts
:marked
hero-detail.component.spec.ts
tr(style=top)
td
:marked
Services
服务
td
:marked
logger.service.spec.ts
:marked
hero.service.spec.ts
:marked
filter-text.service.spec.ts
tr(style=top)
td
:marked
Pipes
管道
td
:marked
ellipsis.pipe.spec.ts
:marked
init-caps.pipe.spec.ts
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="02-11"></a>End to End Test File Names
### <a id="02-11"></a>端到端测试文件名
#### <a href="#02-11">Style 02-11</a>
#### <a href="#02-11">风格02-11</a>
.s-rule.do
:marked
**Do** name end-to-end test specification files after the feature they test with a suffix of `.e2e-spec`.
**坚持**端到端测试配置文件应该和它们所测试的特性同名,并加上后缀`.e2e-spec`。
.s-why
:marked
**Why?** Provides a consistent way to quickly identify end-to-end tests.
**为何?**提供一致的方法快速识别端到端测试文件。
.s-why.s-why-last
:marked
**Why?** Provides pattern matching for test runners and build automation.
**为何?**提供一个与测试运行器和构建自动化相配的模式。
:marked
:marked
- var top="vertical-align:top"
table(width="100%")
col(width="50%")
col(width="50%")
tr
th
p Symbol Name
p 符号名
th
p File Name
p 文件名
tr(style=top)
td
:marked
End to End Tests
端到端测试
td
:marked
app.e2e-spec.ts
:marked
heroes.e2e-spec.ts
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Coding Conventions
## 编程约定
Have consistent set of coding, naming, and whitespace conventions.
坚持一套前后一致的编程、命名和空格的约定。
.l-main-section
:marked
### <a id="03-01"></a>类
#### <a href="#03-01">风格03-01</a>
.s-rule.do
:marked
**Do** use upper camel case when naming classes.
**坚持**使用大写驼峰命名法来命名类。
.s-why
:marked
**Why?** Follows conventional thinking for class names.
**为何?**遵循类命名传统约定。
.s-why.s-why-last
:marked
**Why?** Classes can be instantiated and construct an instance. We often use upper camel case to indicate a constructable asset.
**为何?**类可以被实例化。我们通常使用大写驼峰命名约定来标示可被构造出来的东西。
+makeExample('style-guide/ts/03-01/app/shared/exception.service.avoid.ts', 'example', 'app/shared/exception.service.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/03-01/app/shared/exception.service.ts', 'example', 'app/shared/exception.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="03-02"></a>Constants
### <a id="03-02"></a>常量
#### <a href="#03-02">Style 03-02</a>
#### <a href="#03-02">风格03-02</a>
.s-rule.do
:marked
**Do** declare variables with `const` if their values should not change during the application lifetime.
**坚持**用`const`声明变量,除非它们的值在应用的生命周期内会发生变化。
.s-why
:marked
**Why?** Conveys to readers that the value is invariant.
**为何?** 告诉读者这个值是不可变的。
.s-why.s-why-last
:marked
TypeScript helps enforce that intent by requiring immediate initialization and by
preventing subsequent re-assignment.
TypeScript会要求在声明时立即初始化并阻止对其再次赋值以确保达成我们的意图。
.s-rule.consider
:marked
**Consider** spelling `const` variables in lower camel case.
**考虑** 把常量名拼写为小驼峰格式。
.s-why
:marked
**Why?** lower camel case variable names (`heroRoutes`) are easier to read and understand
than the traditional UPPER_SNAKE_CASE names (`HERO_ROUTES`).
**为何?**小驼峰变量名(`heroRoutes`)比传统的“大写蛇形命名法”(`HERO_ROUTES`)更容易阅读和理解。
.s-why.s-why-last
:marked
**Why?** The tradition of naming constants in UPPER_SNAKE_CASE reflects
an era before the modern IDEs that quickly reveal the `const` declaration.
TypeScript itself prevents accidental reassignment.
**为何?** 把常量命名为大写蛇形命名法的传统源于现代IDE出现之前以便阅读时可以快速发现那些`const`定义。
而TypeScript本身就能够防止意外赋值。
.s-rule.do
:marked
**Do** tolerate _existing_ `const` variables that are spelled in UPPER_SNAKE_CASE.
**坚持** 容许_现存的_`const`变量沿用大写蛇形命名法。
.s-why.s-why-last
:marked
**Why?** Although we recommend creating _new_ constants in lower camel case,
the tradition of UPPER_SNAKE_CASE remains popular and pervasive,
especially in third party modules.
**为何?**虽然我们建议用小驼峰命名法创建_新的_常量但传统的大写驼峰命名法仍然很流行、很普遍特别是在第三方模块中。
+makeExample('style-guide/ts/03-02/app/shared/data.service.ts', '', 'app/shared/data.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="03-03"></a>Interfaces
### <a id="03-03"></a>接口
#### <a href="#03-03">Style 03-03</a>
#### <a href="#03-03">风格03-03</a>
.s-rule.do
:marked
**Do** name an interface using upper camel case.
**坚持**使用大写驼峰命名法来命名接口。
.s-rule.consider
:marked
**Consider** naming an interface without an `I` prefix.
**考虑**不要在接口名字前面加`I`前缀。
.s-why.s-why-last
:marked
**Why?** When we use types, we can often simply use the class as the type.
**为何?**当我们使用类型时,我们经常简单地使用类来作为类型。
+makeExample('style-guide/ts/03-03/app/shared/hero-collector.service.avoid.ts', 'example', 'app/shared/hero-collector.service.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/03-03/app/shared/hero-collector.service.ts', 'example', 'app/shared/hero-collector.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="03-04"></a>Properties and Methods
### <a id="03-04"></a>属性和方法
#### <a href="#03-04">Style 03-04</a>
#### <a href="#03-04">样式03-04</a>
.s-rule.do
:marked
**Do** use lower camel case to name properties and methods.
**坚持**使用小写驼峰命名法来命名属性和方法。
.s-rule.avoid
:marked
**Avoid** prefixing private properties and methods with an underscore.
**避免**使用下划线为前缀来命名私有属性和方法。
.s-why
:marked
**Why?** Follows conventional thinking for properties and methods.
**为何?**遵循传统属性和方法的命名约定。
.s-why
:marked
**Why?** JavaScript lacks a true private property or method.
**为何?**JavaScript不支持真正的私有属性和方法。
.s-why.s-why-last
:marked
**Why?** TypeScript tooling makes it easy to identify private vs public properties and methods.
**为何?**TypeScript工具让识别私有或公有属性和方法变得很简单。
+makeExample('style-guide/ts/03-04/app/shared/toast.service.avoid.ts', 'example', 'app/shared/toast.service.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/03-04/app/shared/toast.service.ts', 'example', 'app/shared/toast.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="03-05"></a>Import Destructuring Spacing
### <a id="03-05"></a>导入语句解构表达式中的空格
#### <a href="#03-05">Style 03-05</a>
#### <a href="#03-05">风格03-05</a>
.s-rule.do
:marked
**Do** leave one whitespace character inside of the `import` statements' curly braces when destructuring.
**坚持**解构时,在`import`声明的大括号里留一个空格字符。
.s-why.s-why-last
:marked
**Why?** Whitespace makes it easier to read the imports.
**为何?**空格让import声明更易于阅读。
+makeExample('style-guide/ts/03-05/app/+heroes/shared/hero.service.avoid.ts', 'example', 'app/+heroes/shared/hero.service.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/03-05/app/+heroes/shared/hero.service.ts', 'example', 'app/+heroes/shared/hero.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="03-06"></a>Import Line Spacing
### <a id="03-06"></a>导入语句中的空行
#### <a href="#03-06">Style 03-06</a>
#### <a href="#03-06">风格03-06</a>
.s-rule.do
:marked
**Do** leave one empty line between third party imports and imports of code we created.
**坚持**在第三方导入和自己代码的导入之间留一个空行。
.s-rule.do
:marked
**Do** list import lines alphabetized by the module.
**坚持**按模块名字的字母顺排列导入行。
.s-rule.do
:marked
**Do** list destructured imported assets alphabetically.
**坚持**在解构表达式中按字母顺序排列导入的东西。
.s-why
:marked
**Why?** The empty line makes it easy to read and locate imports.
**为何?**空行可以让阅读和定位本地导入变得更加容易。
.s-why.s-why-last
:marked
**Why?** Alphabetizing makes it easier to read and locate imports.
**为何?**按字母顺序排列可以让阅读和定位本地导入更加容易。
+makeExample('style-guide/ts/03-06/app/+heroes/shared/hero.service.avoid.ts', 'example', 'app/+heroes/shared/hero.service.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/03-06/app/+heroes/shared/hero.service.ts', 'example', 'app/+heroes/shared/hero.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Application Structure
## 应用程序结构
Have a near term view of implementation and a long term vision. Start small but keep in mind where the app is heading down the road.
准备一个短期和一个长期的实施方案。从零开始,但要时刻考虑应用程序接下来要走的路。
All of the app's code goes in a folder named `app`. All content is 1 feature per file. Each component, service, and pipe is in its own file. All 3rd party vendor scripts are stored in another folder and not in the `app` folder. We didn't write them and we don't want them cluttering our app. Use the naming conventions for files in this guide.
把所有应用程序的源代码都放到名叫`app`的目录里。所有内容都遵循每个文件单个特性的原则。每个组件、服务和管道都在自己的文件里。
所有第三方程序包都被保存到其它目录里而不在`app`目录里,我们不会修改它们,所以不希望它们弄乱我们的应用程序。使用本指南介绍的文件命名约定。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-01"></a>LIFT
#### <a href="#04-01">Style 04-01</a>
#### <a href="#04-01">风格04-01</a>
.s-rule.do
:marked
**Do** structure the app such that we can `L`ocate our code quickly, `I`dentify the code at a glance, keep the `F`lattest structure we can, and `T`ry to be DRY.
**坚持**组织应用的结构,达到这些目的:快速定位(`L`ocate)代码、一眼识别(`I`dentify)代码、尽量保持平面化结构(`F`lattest)和尝试`T`ry遵循不重复自己DRY - Do Not Repeat Yourself约定。
.s-rule.do
:marked
**Do** define the structure to follow these four basic guidelines, listed in order of importance.
**坚持**遵循四个基本指导原则来定义文件结构,上面四个基本原则是按重要顺序排列的。
.s-why.s-why-last
:marked
**Why?** LIFT Provides a consistent structure that scales well, is modular, and makes it easier to increase developer efficiency by finding code quickly. Another way to check our app structure is to ask ourselves: How quickly can we open and work in all of the related files for a feature?
**为何?**LIFT提供了前后一致的结构它具有扩展性强、模块化的特性。因为容易快速锁定代码所以提高了开发者的效率。另外检查应用结构的方法是问问自己我们打开和编辑与某个特性相关的所有文件的速度如何
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-02"></a>Locate
### <a id="04-02"></a>定位
#### <a href="#04-02">Style 04-02</a>
#### <a href="#04-02">风格04-02</a>
.s-rule.do
:marked
**Do** make locating our code intuitive, simple and fast.
**坚持**直观、简单和快速的定位我们的代码。
.s-why.s-why-last
:marked
**Why?** We find this to be super important for a project. If we cannot find the files we need to work on quickly, we will not be able to work as efficiently as possible, and the structure will need to change. We may not know the file name or where its related files are, so putting them in the most intuitive locations and near each other saves a ton of time. A descriptive folder structure can help with this.
**为何?**定位对项目是非常重要的。如果我们不能快速找到需要工作的文件,我们就不可能在最佳效率状态下面工作,结构就需要更换。我们可能不知道文件的名称或者文件所在目录名,所以我们把它们放到直观的地方,一个挨着一个,这样可以节省很多时间。坚持说明性强的文件结构会有很大帮助。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-03"></a>Identify
### <a id="04-03"></a>识别
#### <a href="#04-03">Style 04-03</a>
#### <a href="#04-03">风格04-03</a>
.s-rule.do
:marked
**Do** name the file such that we instantly know what it contains and represents.
**坚持**命名文件到这个程度:可以从名字立刻知道它包含了什么,代表了什么。
.s-rule.do
:marked
**Do** be descriptive with file names and keep the contents of the file to exactly one component.
**坚持**文件名要具有说明性,并保证文件中只包含一个组件。
.s-rule.avoid
:marked
**Avoid** files with multiple components, multiple services, or a mixture.
**避免**创建包含很多组件、服务或者混合体的文件。
.s-why.s-why-last
:marked
**Why?** We spend less time hunting and pecking for code, and become more efficient. If this means we want longer file names, then so be it.
**为何?**我们花费更少的时间来查找和琢磨代码,工作更有效率。如果这意味着更长的文件名,长就长吧。
.l-sub-section
:marked
There are deviations of the 1 per file rule when we have a set of very small features that are all related to each other, as they are still easily identifiable.
当我们有一套非常小并且互相关联的特性时,我们可能不必坚持单文件单组件的约定,因为它们仍然非常易于被识别。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-04"></a>Flat
### <a id="04-04"></a>平面化
#### <a href="#04-04">Style 04-04</a>
#### <a href="#04-04">风格04-04</a>
.s-rule.do
:marked
**Do** keep a flat folder structure as long as possible.
**坚持**尽可能保持平面化的目录结构。
.s-rule.consider
:marked
**Consider** creating fodlers when we get to seven or more files.
**考虑**当我们有7个或更多文件时才新建目录。
.s-why.s-why-last
:marked
**Why?** Nobody wants to search seven levels of folders to find a file. In a folder structure there is no hard and fast number rule, but when a folder has seven to ten files, that may be time to create subfolders. We base it on our comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder.
**为何?**没有人愿意搜索7层目录来找一个文件。在目录结构中没有硬数字约定但是当目录有七到十个文件时就是需要新建子目录的时候了。这是基于舒适级别而定的。以平面化结构开始在有很明显的需求时再新建目录(来配合其他LIFT约定)
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-05"></a>T-DRY (Try to be DRY)
### <a id="04-05"></a>T-DRY (尝试遵循不重复自己DRY的约定)
#### <a href="#04-05">Style 04-05</a>
#### <a href="#04-05">风格04-05</a>
.s-rule.do
:marked
**Do** be DRY (Don't Repeat Yourself)
**坚持**不要重复自己(DRY)
.s-rule.avoid
:marked
**Avoid** being so DRY that we sacrifice readability.
**避免**过度DRY以致牺牲了阅读性。
.s-why.s-why-last
:marked
**Why?** Being DRY is important, but not crucial if it sacrifices the others in LIFT, which is why we call it T-DRY. We dont want to type `hero-view.component.html` for a view because, well, its obviously a view. If it is not obvious or by convention, then we name it.
**为何?**虽然不重复自己约定很重要但是如果要牺牲其他的LIFT约定它就不是最重要的这就是为什么我们说**尝试**不重复自己(T-DRY)。我们不愿意为了视图使用`hero-view.component.html`,因为它很明显就是一个视图。如果它不是很明显,那么我们就把视图单词加到它的名字里。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-06"></a>Overall Structural Guidelines
### <a id="04-06"></a>总体结构指导原则
#### <a href="#04-06">Style 04-06</a>
#### <a href="#04-06">风格04-06</a>
.s-rule.do
:marked
**Do** start small but keep in mind where the app is heading down the road.
**坚持**从零开始,但要时刻考虑应用程序接下来要走的路。
.s-rule.do
:marked
**Do** have a near term view of implementation and a long term vision.
**坚持**有一个短期和一个长期的实施方案。
.s-rule.do
:marked
**Do** put all of the app's code in a folder named `app`.
**坚持**把所有源代码都放到名为`app`的目录里。
.s-rule.consider
:marked
**Consider** creating a folder for each component including its `.ts`, `.html`, `.css` and `.spec` file.
**考虑**为每个组件新建一个目录,保存它的`.ts`,`.html`,`.css`,`.spec`等文件。
.s-why
:marked
**Why?** Helps us keep the app structure small and easy to maintain in the early stages, while being easy to evolve as the app grows.
**为何?** 帮助我们在早期保持应用结构的精简与可维护性,同时保证在应用程序成长的过程中,结构易于演化。
.s-why.s-why-last
:marked
**Why?** Components often have four files (e.g. `*.html`, `*.css`, `*.ts`, and `*.spec.ts`) and can clutter a folder quickly.
**为何?**组件通常有四个文件(例如`*.html`、 `*.css`、 `*.ts` 和 `*.spec.ts`),它们很容易把一个目录弄乱。
.example-title Overall Folder and File Structure 整体目录和文件结构
.filetree
.file src
.children
.file app
.children
.file +heroes
.children
.file hero
.children
.file hero.component.ts|html|css|spec.ts
.file index.ts
.file hero-list
.children
.file hero-list.component.ts|html|css|spec.ts
.file index.ts
.file shared
.children
.file hero.model.ts
.file hero.service.ts|spec.ts
.file index.ts
.file heroes.component.ts|html|css|spec.ts
.file index.ts
.file shared
.children
.file ...
.file app.component.ts|html|css|spec.ts
.file main.ts
.file index.html
.file ...
:marked
.l-sub-section
:marked
While we prefer our Components to be in their own dedicated folder, another option for small apps is to keep Components flat (not in a dedicated folder). This adds up to four files to the existing folder, but also reduces the folder nesting. Be consistent.
虽然我们比较喜欢把组件放到它自己独立的目录里面,但是对于很小应用来说,另一个选项是保持平面化结构(不在自己独立的目录里)。这样我们添加最多四个文件到一个已有的目录,但是同时减少的目录的嵌套。保持前后一致就好。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-07"></a>Shared Folder
### <a id="04-07"></a>共享目录
#### <a href="#04-07">Style 04-07</a>
#### <a href="#04-07">风格04-07</a>
.s-rule.do
:marked
**Do** put all shared files within a component feature in a `shared` folder.
**坚持**在单个特性范围内,把所有共享的文件放到`shared`目录。
.s-rule.consider
:marked
**Consider** creating a folder for each component including its `.ts`, `.html`, `.css` and `.spec` file.
**考虑**为每个组件新建一个目录,保存它的`.ts`、`.html`、`.css`和`.spec` 文件。
.s-why
:marked
**Why?** Separates shared files from the components within a feature.
**为何?**在一个特性范围内,分离出组件共享的文件。
.s-why.s-why-last
:marked
**Why?** Makes it easier to locate shared files within a component feature.
**为何?**使得在一个特性范围内,更加易于定位共享文件。
.example-title Shared Folder 共享的目录
.filetree
.file src
.children
.file app
.children
.file +heroes
.children
.file hero
.children
.file ...
.file hero-list
.children
.file ...
.file shared
.children
.file hero-button
.children
.file ...
.file hero.model.ts
.file hero.service.ts|spec.ts
.file index.ts
.file heroes.component.ts|html|css|spec.ts
.file index.ts
.file shared
.children
.file exception.service.ts|spec.ts
.file index.ts
.file nav
.children
.file ...
.file app.component.ts|html|css|spec.ts
.file main.ts
.file index.html
.file ...
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-08"></a>Folders-by-Feature Structure
### <a id="04-08"></a>根据特性划分的目录结构
#### <a href="#04-08">Style 04-08</a>
#### <a href="#04-08">风格04-08</a>
.s-rule.do
:marked
**Do** create folders named for the feature they represent.
**坚持**把目录的名字命名为它包含的特性名字。
.s-why
:marked
**Why?** A developer can locate the code, identify what each file represents at a glance, the structure is as flat as it can be, and there is no repetitive nor redundant names.
**为何?**开发者能定位代码,一眼就能看出每个文件是干什么的,结构尽可能平面化,并且没有重复或多余的名字。
.s-why
:marked
**Why?** The LIFT guidelines are all covered.
**为何?**遵循LIFT指导原则。
.s-why
:marked
**Why?** Helps reduce the app from becoming cluttered through organizing the content and keeping them aligned with the LIFT guidelines.
**为何?**在管理应用内容时帮助减少把程序结构弄得很杂乱的可能性确保它们向LIFT指导原则看齐。
.s-why.s-why-last
:marked
**Why?** When there are a lot of files (e.g. 10+) locating them is easier with a consistent folder structures and more difficult in flat structures.
**为何?**当有很多文件(10个以上)的时候,在一致的目录结构下面,比在平面化结构下面定位它们要容易得多。
:marked
Below is an example of a small app with folders per component.
下面是一个小应用使用单组件目录的例子。
.example-title Folders per Component 单组件目录
.filetree
.file src
.children
.file app
.children
.file +heroes
.children
.file hero
.children
.file ...
.file hero-list
.children
.file ...
.file shared
.children
.file ...
.file heroes.component.ts|html|css|spec.ts
.file index.ts
.file +villains
.children
.file villain
.children
.file ...
.file villain-list
.children
.file ...
.file shared
.children
.file ...
.file villains.component.ts|html|css|spec.ts
.file index.ts
.file shared
.children
.file nav
.children
.file ...
.file ...
.file app.component.ts|html|css|spec.ts
.file main.ts
.file index.html
.file ...
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-09"></a>Layout Components
### <a id="04-09"></a>布局组件
#### <a href="#04-09">Style 04-09</a>
#### <a href="#04-09">风格04-09</a>
.s-rule.do
:marked
**Do** put components that define the overall layout in a `shared` folder.
**坚持**把定义总体布局的组件放到`shared`目录。
.s-rule.do
:marked
**Do** put shared layout components in their own folder, under the `shared` folder.
**坚持**把共享的布局组件放到`shared`目录下它自己的独立目录里。
.s-why
:marked
**Why?** We need a place to host our layout for our app. Our navigation bar, footer, and other aspects of the app that are needed for the entire app.
**为何?**我们需要一个地方来存放应用程序的布局,比如导航条、页脚和其它整个应用中都需要的东西。
.s-why.s-why-last
:marked
**Why?** Organizes all layout in a consistent place re-used throughout the application.
**为何?**在前后一致的地方管理所有布局,在整个应用程序范围内重复使用。
.example-title Folder for Layout Components 布局组件目录
.filetree
.file src
.children
.file app
.children
.file +heroes
.children
.file ...
.file shared
.children
.file nav
.children
.file index.ts
.file nav.component.ts|html|css|spec.ts
.file footer
.children
.file index.ts
.file footer.component.ts|html|css|spec.ts
.file index.ts
.file ...
.file app.component.ts|html|css|spec.ts
.file main.ts
.file index.html
.file ...
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-10"></a>Create and Import Barrels
### <a id="04-10"></a>创建和导入封装桶
#### <a href="#04-10">Style 04-10</a>
#### <a href="#04-10">风格04-10</a>
.s-rule.consider
:marked
**Consider** creating a file that imports, aggregates, and re-exports items. We call this technique a **barrel**.
**考虑**新建一个文件,用来导入、归集和重新导出项目。该技巧被称作**封装桶**。
.s-rule.consider
:marked
**Consider** naming this barrel file `index.ts`.
**考虑**把该封装桶文件命名为`index.ts`。
.s-why
:marked
**Why?** A barrel aggregates many imports into a single import.
**为何?**封装桶把多个导入合并成一个单独的导入。
.s-why
:marked
**Why?** A barrel reduces the number of imports a file may need.
**为何?**封装桶减少文件可能需要导入的数量。
.s-why
:marked
**Why?** A barrel provides a consistent pattern to import everything exported in the barrel from a folder.
**为何?** 封装通提供一致连贯的模式,用来导入从一个目录中的封装的所有导出的东西。
.s-why
:marked
**Why?** This is consistent with a pattern from Node, which imports the index.js|ts file from a folder.
**为何?** 这是一个从Node沿袭的一致连贯模式用来从一个目录导入index.js|ts。
.s-why.s-why-last
:marked
**Why?** A barrel shortens import statements.
**为何?**封装桶精简了导入声明。
+makeTabs(
`style-guide/ts/04-10/app/shared/index.ts,
style-guide/ts/04-10/app/shared/filter-text/index.ts,
style-guide/ts/04-10/app/shared/modal/index.ts,
style-guide/ts/04-10/app/shared/nav/index.ts,
style-guide/ts/04-10/app/shared/spinner/index.ts,
style-guide/ts/04-10/app/shared/toast/index.ts`,
`example,,,,,`,
`app/shared/index.ts,
app/shared/filter-text/index.ts,
app/shared/modal/index.ts,
app/shared/nav/index.ts,
app/shared/spinner/index.ts,
app/shared/toast/index.ts`)
:marked
.example-title Folder Barrels 封装桶目录
.filetree
.file src
.children
.file app
.children
.file +dashboard
.children
.file ...
.file index.ts
.file +heroes
.children
.file ...
.file index.ts
.file shared
.children
.file nav
.children
.file ...
.file index.ts
.file search
.children
.file ...
.file index.ts
.file ...
.file index.ts
.file app.component.ts|html|css|spec.ts
.file main.ts
.file index.html
.file ...
:marked
+makeExample('style-guide/ts/04-10/app/+heroes/heroes.component.avoid.ts', 'example', 'app/+heroes/heroes.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/04-10/app/+heroes/heroes.component.ts', 'example', 'app/+heroes/heroes.component.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-11"></a>Lazy Loaded Folders
### <a id="04-11"></a>惰性加载目录
#### <a href="#04-11">Style 04-11</a>
#### <a href="#04-11">风格04-11</a>
A distinct application feature or workflow may be *lazy loaded* or *loaded on demand* rather than when the application starts.
一个独特的应用程序特性或者工作流可能被**惰性加载**或**按需加载**,而非在应用程序启动时就全部加载。
.s-rule.do
:marked
**Do** put the contents of lazy loaded features in a *lazy loaded folder*. A typical *lazy loaded folder* contains a *routing component*, its child components, and their related assets and modules.
**坚持**把惰性加载特性的文件放到**惰性加载目录**。典型的*惰性加载目录*中包含*路由组件*、子级组件和相关的东西和模块。
.s-why.s-why-last
:marked
**Why?** The folder makes it easy to identify and isolate the feature content.
**为何?**该文件夹易于识别和隔离特性内容。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-12"></a>Prefix Lazy Loaded Folders with +
### <a id="04-12"></a>为惰性加载目录名字加前缀+
#### <a href="#04-12">Style 04-12</a>
#### <a href="#04-12">样式04-12</a>
.s-rule.do
:marked
**Do** prefix the name of a *lazy loaded folder* with a (+) e.g., `+dashboard/`.
**坚持**使用一个(+)前缀来标记*惰性加载目录*名字,比如`+dashboard/`。
.s-why
:marked
**Why?** Lazy loaded code paths are easily identifiable by their `+` prefix.
**为何?**通过`+`前缀,惰性加载的源代码可以很容易被识别。
.s-why
:marked
**Why?** Lazy loaded code paths are easily distinguishable from non lazy loaded paths.
**为何?**惰性加载路径和非惰性加载的路径很容易被区分开来。
.s-why.s-why-last
:marked
**Why?** If we see an `import` path that contains a `+`, we can quickly refactor to use lazy loading.
**为何?**如果看到包含`+`的`import`路径,我们能快速使用惰性加载进行重构。
.example-title Lazy Loaded Folders 惰性加载目录
.filetree
.file src
.children
.file app
.children
.file +dashboard
.children
.file dashboard.component.ts|html|css|spec.ts
.file index.ts
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-13"></a>Never Directly Import Lazy Loaded Folders
### <a id="04-13"></a>决不直接导入惰性加载目录
#### <a href="#04-13">Style 04-13</a>
#### <a href="#04-13">风格04-13</a>
.s-rule.avoid
:marked
**Avoid** allowing modules in sibling and parent folders to directly import a module in a *lazy loaded feature*.
**避免**允许兄弟或者父目录里的模块直接导入*惰性加载特性*模块。
.s-why.s-why-last
:marked
**Why?** Directly importing a module loads it immediately when our intention is to load it on demand.
**为何?**直接导入模块会立刻加载它,但是我们的原意是按需加载。
+makeExample('style-guide/ts/04-13/app/app.component.avoid.ts', 'example', 'app/app.component.ts')(avoid=1)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-14"></a>Lazy Loaded Folders May Import From a Parent
### 惰性加载目录可以导入父级
#### <a href="#04-14">Style 04-14</a>
#### <a href="#04-14">样式04-14</a>
.s-rule.do
:marked
**Do** allow lazy loaded modules to import a module from a parent folder.
**坚持**允许惰性加载模块导入父级目录的模块。
.s-why.s-why-last
:marked
**Why?** A parent module has already been loaded by the time the lazy loaded module imports it.
**为何?**在惰性加载模块导入父级模块的时候,父级模块早已经被加载了。
+makeExample('style-guide/ts/04-14/app/+heroes/heroes.component.ts', 'example', 'app/+heroes/heroes.component.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="04-15"></a>Use Component Router to Lazy Load
### <a id="04-15"></a>使用组件路由器来惰性加载
#### <a href="#04-15">Style 04-15</a>
#### <a href="#04-15">风格04-15</a>
.s-rule.do
:marked
**Do** use the Component Router to lazy load routable features.
**坚持**使用组件路由器来惰性加载可以路由的特性。
.s-why.s-why-last
:marked
**Why?** That's the easiest way to load a module on demand.
**为何?**这是最简单的按需加载模块的方法。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Components
### <a id="05-02"></a>Components Selector Naming
### <a id="05-02"></a>组件选择器命名
#### <a href="#05-02">Style 05-02</a>
#### <a href="#05-02">风格05-02</a>
.s-rule.do
:marked
**Do** use `kebab-case` for naming the element selectors of our components.
**坚持**使用`烤串命名法(中线命名法)`来命名组件的元素选择器。
.s-why.s-why-last
:marked
**Why?** Keeps the element names consistent with the specification for [Custom Elements](https://www.w3.org/TR/custom-elements/).
**为何?**保持元素命名与[自定义元素](https://www.w3.org/TR/custom-elements/)命名规范一致。
+makeExample('style-guide/ts/05-02/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')(avoid=1)
:marked
+makeTabs(
`style-guide/ts/05-02/app/heroes/shared/hero-button/hero-button.component.ts,
style-guide/ts/05-02/app/app.component.html`,
'example,',
`app/heroes/shared/hero-button/hero-button.component.ts,
app/app.component.html`)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-03"></a>Components as Elements
### <a id="05-03"></a>把组件当做元素
#### <a href="#05-03">Style 05-03</a>
#### <a href="#05-03">风格05-03</a>
.s-rule.do
:marked
**Do** define Components as elements via the selector.
**坚持**通过选择器来定义充当元素的组件。
.s-why
:marked
**Why?** Components have templates containing HTML and optional Angular template syntax. They are most associated with putting content on a page, and thus are more closely aligned with elements.
**为何?**组件有模板包含HTML和可能有的Angular模板语法。它们大多数都是用来在页面上面放置内容的所以与元素更加类似。
.s-why
:marked
**Why?** Components are derived from Directives, and thus their selectors can be elements, attributes, or other selectors. Defining the selector as an element provides consistency for components that represent content with a template.
**为何?**组件是从指令派生出来的,所以它们的选择器可以是元素、特性或者其他选择器。把选择器作为元素来定义,统一了通过模块提供内容的组件。
.s-why.s-why-last
:marked
**Why?** It is easier to recognize that a symbol is a component vs a directive by looking at the template's html.
**为何?**查看组件是否有模板HTML文件是最简单的识别一个符号是组件还是指令的方法。
+makeExample('style-guide/ts/05-03/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/hero-button/hero-button.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-03/app/app.component.avoid.html', '', 'app/app.component.html')(avoid=1)
:marked
+makeTabs(
`style-guide/ts/05-03/app/heroes/shared/hero-button/hero-button.component.ts,
style-guide/ts/05-03/app/app.component.html`,
'example,',
`app/heroes/shared/hero-button/hero-button.component.ts,
app/app.component.html`)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-04"></a>Extract Template and Styles to Their Own Files
### <a id="05-04"></a>把模板和样式提取到它们自己的文件
#### <a href="#05-04">Style 05-04</a>
#### <a href="#05-04">风格05-04</a>
.s-rule.do
:marked
**Do** extract templates and styles into a separate file, when more than 3 lines.
**坚持**当超过三行的时候,把模板和样式提取到一个单独的文件。
.s-rule.do
:marked
**Do** name the template file `[component-name].component.html`, where [component-name] is our component name.
**坚持**当组件名字为[component-name]的时候,命名它的模板为`[component-name].component.html`。
.s-rule.do
:marked
**Do** name the style file `[component-name].component.css`, where [component-name] is our component name.
**坚持**当组件名字为[component-name]时,命名它的样式为`[component-name].component.css`。
.s-why
:marked
**Why?** Syntax hints for inline templates in (*.js and *.ts) code files are not supported by some editors.
**为何?**在(*.js和*.ts)代码里面内联模板时,一些编辑器不支持语法提示。
.s-why.s-why-last
:marked
**Why?** A component file's logic is easier to read when not mixed with inline template and styles.
**为何?**当没有与内联模板和样式混合的时候,组件文件里的逻辑更加易于阅读。
+makeExample('style-guide/ts/05-04/app/heroes/heroes.component.avoid.ts', 'example', 'app/heroes/heroes.component.ts')(avoid=1)
:marked
+makeTabs(
`style-guide/ts/05-04/app/heroes/heroes.component.ts,
style-guide/ts/05-04/app/heroes/heroes.component.html,
style-guide/ts/05-04/app/heroes/heroes.component.css`,
'example,,',
`app/heroes/heroes.component.ts,
app/heroes/heroes.component.html,
app/heroes/heroes.component.css`)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-12"></a>Decorate Input and Output Properties Inline
### <a id="05-12"></a>内联Input和Output属性装饰器
#### <a href="#05-12">Style 05-12</a>
#### <a href="#05-12">风格05-12</a>
.s-rule.do
:marked
**Do** use [`@Input`](https://angular.io/docs/ts/latest/api/core/index/Input-var.html) and [`@Output`](https://angular.io/docs/ts/latest/api/core/index/Output-var.html) instead of the `inputs` and `outputs` properties of the [`@Directive`](https://angular.io/docs/ts/latest/api/core/index/Directive-decorator.html) and [`@Component`](https://angular.io/docs/ts/latest/api/core/index/Component-decorator.html) decorators:
**坚持**使用[`@Input`](https://angular.io/docs/ts/latest/api/core/Input-var.html)和[`@Output`](https://angular.io/docs/ts/latest/api/core/Output-var.html), 而非[`@Directive`](https://angular.io/docs/ts/latest/api/core/Directive-decorator.html) 和 [`@Component`](https://angular.io/docs/ts/latest/api/core/Component-decorator.html) 装饰器里面的`inputs`和`outputs`属性。
.s-rule.do
:marked
**Do** place the `@Input()` or `@Output()` on the same line as the property they decorate.
**坚持**把`@Input()`或者`@Output()`放到它们装饰的属性的同一行。
.s-why
:marked
**Why?** It is easier and more readable to identify which properties in a class are inputs or outputs.
**为何?**这样易于在类里面识别哪个属性是inputs或outputs。
.s-why
:marked
**Why?** If we ever need to rename the property or event name associated to [`@Input`](https://angular.io/docs/ts/latest/api/core/index/Input-var.html) or [`@Output`](https://angular.io/docs/ts/latest/api/core/index/Output-var.html) we can modify it on a single place.
**为何?**如果我们需要重命名[`@Input`](https://angular.io/docs/ts/latest/api/core/Input-var.html) 或 [`@Output`](https://angular.io/docs/ts/latest/api/core/Output-var.html)关的属性或者事件,我们可以在一个地方修改。
.s-why
:marked
**Why?** The metadata declaration attached to the directive is shorter and thus more readable.
**为何?**依附到指令的元数据声明会比较简短,更易于阅读。
.s-why.s-why-last
:marked
**Why?** Placing the decorator on the same line makes for shorter code and still easily identifies the property as an input or output.
**为何?**把装饰器放到同一行可以精简代码,同时更易于识别输入或输出属性。
+makeExample('style-guide/ts/05-12/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-12/app/heroes/shared/hero-button/hero-button.component.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-13"></a>Avoid Renaming Inputs and Outputs
### <a id="05-13"></a>避免重命名输入和输出
#### <a href="#05-13">Style 05-13</a>
#### <a href="#05-13">风格05-13</a>
.s-rule.avoid
:marked
**Avoid** renaming inputs and outputs, when possible.
**避免**重命名输入和输出。
.s-why.s-why-last
:marked
**Why?** May lead to confusion when the output or the input properties of a given directive are named a given way but exported differently as a public API.
**为何?**可能导致混乱造成指令的输入或输出属性的名字与导出的公共API名字不一样。
+makeExample('style-guide/ts/05-13/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-13/app/app.component.avoid.html', '', 'app/app.component.html')(avoid=1)
:marked
+makeTabs(
`style-guide/ts/05-13/app/heroes/shared/hero-button/hero-button.component.ts,
style-guide/ts/05-13/app/app.component.html`,
'example,',
`app/heroes/shared/hero-button/hero-button.component.ts,
app/app.component.html`)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-14"></a>Member Sequence
### <a id="05-14"></a>成员顺序
#### <a href="#05-14">Style 05-14</a>
#### <a href="#05-14">风格05-14</a>
.s-rule.do
:marked
**Do** place properties up top followed by methods.
**坚持**把属性成员放到顶部,方法成员紧随其后。
.s-rule.do
:marked
**Do** place private members after public members, alphabetized.
**坚持**先放公共成员,再放私有成员,并按照字母顺序排列。
.s-why.s-why-last
:marked
**Why?** Placing members in a consistent sequence makes it easy to read and helps we instantly identify which members of the component serve which purpose.
**为何?**使用一致的顺序放置成员,可以增加阅读性,并帮助我们立刻识别出组件里面哪个成员是干什么的。
+makeExample('style-guide/ts/05-14/app/shared/toast/toast.component.avoid.ts', 'example', 'app/shared/toast/toast.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-14/app/shared/toast/toast.component.ts', 'example', 'app/shared/toast/toast.component.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-15"></a>Put Logic in Services
### <a id="05-15"></a>把逻辑放到服务里
#### <a href="#05-14">Style 05-15</a>
#### <a href="#05-14">风格05-15</a>
.s-rule.do
:marked
**Do** limit logic in a component to only that required for the view. All other logic should be delegated to services.
**坚持**把组件类中的逻辑限制到只有视图需要的逻辑。所有其它逻辑都应该被放到服务。
.s-rule.do
:marked
**Do** move reusable logic to services and keep components simple and focused on their intended purpose.
**坚持**把可以重复使用的逻辑放到服务里,保持组件简单并聚焦于它们预期目的。
.s-why
:marked
**Why?** Logic may be reused by multiple components when placed within a service and exposed via a function.
**为何?**当逻辑被放置到服务里并以函数的形式暴露时,它可以被多个组件重复使用。
.s-why
:marked
**Why?** Logic in a service can more easily be isolated in a unit test, while the calling logic in the component can be easily mocked.
**为何?**在单元测试时服务里的逻辑更加容易被隔离。在组件里调用它的逻辑也很容易被模仿Mock。
.s-why
:marked
**Why?** Removes dependencies and hides implementation details from the component.
**为何?**从组件移除依赖并隐藏实施细节。
.s-why.s-why-last
:marked
**Why?** Keeps the component slim, trim, and focused.
**为何?**保持组件苗条、精简和聚焦
+makeExample('style-guide/ts/05-15/app/heroes/hero-list/hero-list.component.avoid.ts', '', 'app/heroes/hero-list/hero-list.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-15/app/heroes/hero-list/hero-list.component.ts', 'example', 'app/heroes/hero-list/hero-list.component.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-16"></a>Don't Prefix Output Properties
### <a id="05-16"></a>不要给输出属性加前缀
#### <a href="#05-16">Style 05-16</a>
#### <a href="#05-16">风格05-16</a>
.s-rule.do
:marked
**Do** name events without the prefix `on`.
**坚持**命名事件时,不要带前缀`on`。
.s-rule.do
:marked
**Do** name our event handler methods with the prefix `on` followed by the event name.
**坚持**命名事件处理方法时,带前缀`on`,紧跟事件名字。
.s-why
:marked
**Why?** This is consistent with built-in events such as button clicks.
**为何?**与内建事件命名一致,比如按钮点击。
.s-why.s-why-last
:marked
**Why?** Angular allows for an [alternative syntax](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#binding-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
**为何?**Angular允许[另一种备选语法](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#binding-syntax) `on-*`。如果事件的名字本身带有前缀`on`,那么绑定的表达式可能是`on-onEvent`。
+makeExample('style-guide/ts/05-16/app/heroes/hero.component.avoid.ts', 'example', 'app/heroes/hero.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-16/app/app.component.avoid.html', '', 'app/app.component.html')(avoid=1)
:marked
+makeTabs(
`style-guide/ts/05-16/app/heroes/hero.component.ts,
style-guide/ts/05-16/app/app.component.html`,
'example,',
`app/heroes/hero.component.ts,
app/app.component.html`)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="05-17"></a>把展示逻辑放到组件类里
#### <a href="#05-17">Style 05-17</a>
#### <a href="#05-17">风格05-17</a>
.s-rule.do
:marked
**Do** put presentation logic in the Component class, and not in the template.
**坚持**把展示逻辑放到组件类里,而非模板里。
.s-why
:marked
**Why?** Logic will be contained in one place (the Component class) instead of being spread in two places.
**为何?**所有逻辑都被放置到一个地方(组件类),而不被分离到两个地方。
.s-why.s-why-last
:marked
**Why?** Keeping the component's presentation logic in the class instead of the template improves testability, maintainability, and reusability.
**为何?**将组件的展示逻辑放到组件类而非模板里,可以增强测试性、维护性和重复使用性。
+makeExample('style-guide/ts/05-17/app/heroes/hero-list/hero-list.component.avoid.ts', 'example', 'app/heroes/hero-list/hero-list.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/05-17/app/heroes/hero-list/hero-list.component.ts', 'example', 'app/heroes/hero-list/hero-list.component.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Directives
## 指令
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="06-01"></a>Use Directives to Enhance an Existing Element
### <a id="06-01"></a>使用指令来加强已有元素
#### <a href="#06-01">Style 06-01</a>
#### <a href="#06-01">风格06-01</a>
.s-rule.do
:marked
**Do** use attribute directives when you have presentation logic without a template.
**坚持**当你需要有无模板的展示逻辑时,使用属性型指令。
.s-why
:marked
**Why?** Attributes directives don't have an associated template.
**为何?**属性型指令没有配套的模板。
.s-why.s-why-last
:marked
**Why?** An element may have more than one attribute directive applied.
**为何?**一个元素可能使用多个属性型指令。
+makeExample('style-guide/ts/06-01/app/shared/highlight.directive.ts', 'example', 'app/shared/highlight.directive.ts')
:marked
+makeExample('style-guide/ts/06-01/app/app.component.html', null, 'app/app.component.html')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="06-03"></a>Use HostListener and HostBinding Class Decorators
### <a id="06-03"></a>使用HostListener和HostBinding类装饰器
#### <a href="#06-03">Style 06-03</a>
#### <a href="#06-03">风格06-03</a>
.s-rule.do
:marked
**Do** use @HostListener and @HostBinding instead of the host property of the @Directive and @Component decorators:
**坚持**使用@HostListener和@HostBinding而非@Directive和@Component装饰器的宿主属性。
.s-why
:marked
**Why?** The property or method name associated with @HostBinding or respectively @HostListener should be modified only in a single place - in the directive's class. In contrast if we use host we need to modify both the property declaration inside the controller, and the metadata associated to the directive.
**为何?**与属性或方法名字相关联的@HostBinding或者@HostListener应该只在一个地方被修改在指令的类里。反过来如果我们使用宿主属性我们需要在控制器内修改属性声明然后在指令相关的元数据里修改。
.s-why.s-why-last
:marked
**Why?** The metadata declaration attached to the directive is shorter and thus more readable.
**为何?**指令附带的元数据声明会简短一些,易于阅读。
+makeExample('style-guide/ts/06-03/app/shared/validator.directive.avoid.ts', 'example', 'app/shared/validator.directive.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/06-03/app/shared/validator.directive.ts', 'example', 'app/shared/validator.directive.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Services
## 服务
### <a id="07-01"></a>Services are Singletons in Same Injector
### <a id="07-01"></a>在同一个注入器内,服务是单例
#### <a href="#07-01">Style 07-01</a>
#### <a href="#07-01">风格07-01</a>
.s-rule.do
:marked
**Do** use services as singletons within the same injector. Use them for sharing data and functionality.
**坚持**在同一个注入器内,把服务当做单例使用。使用它们来共享数据和功能。
.s-why
:marked
**Why?** Services are ideal for sharing methods across a feature area or an app.
**为何?**服务是在一个特性范围或一个应用内理想的共享方法的理想载体。
.s-why.s-why-last
:marked
**Why?** Services are ideal for sharing stateful in-memory data.
**为何?**服务是共享状态性内存数据的理想方法。
+makeExample('style-guide/ts/07-01/app/heroes/shared/hero.service.ts', 'example', 'app/heroes/shared/hero.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="07-02"></a>Single Responsibility
### <a id="07-02"></a>单一职责
#### <a href="#07-02">Style 07-02</a>
#### <a href="#07-02">风格07-02</a>
.s-rule.do
:marked
**Do** create services with a single responsibility that is encapsulated by its context.
**坚持**新建单一职责的服务,把它封装在自己的环境内。
.s-rule.do
:marked
**Do** create a new service once the service begins to exceed that singular purpose.
**坚持**当服务成长到超出单一用途时,新建一个服务。
.s-why
:marked
**Why?** When a service has multiple responsibilities, it becomes difficult to test.
**为何?**当服务有多个职责时,它很难被测试。
.s-why.s-why-last
:marked
**Why?** When a service has multiple responsibilities, every Component or Service that injects it now carries the weight of them all.
**为何?**当服务有多个职责时,每个注入它的组件或者服务都会被迫承担它们的(多个职责)所有的重量。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="07-03"></a>Providing a Service
### <a id="07-03"></a>提供一个服务
#### <a href="#07-03">Style 07-03</a>
#### <a href="#07-03">风格07-03</a>
.s-rule.do
:marked
**Do** provide services to the Angular 2 injector at the top-most component where they will be shared.
**坚持**在被共享范围内的顶级组件里将服务提供到Angular 2的注入器里。
.s-why
:marked
**Why?** The Angular 2 injector is hierarchical.
**为何?**Angular 2注入器是层次性的。
.s-why
:marked
**Why?** When providing the service to a top level component, that instance is shared and available to all child components of that top level component.
**为何?**在顶层组件提供服务时,该服务实例在所有该顶级组件的子级组件中可见并共享。
.s-why
:marked
**Why?** This is ideal when a service is sharing methods or state.
**为何?**服务是共享方法或状态的理想方法。
.s-why.s-why-last
:marked
**Why?** This is not ideal when two different components need different instances of a service. In this scenario it would be better to provide the service at the component level that needs the new and separate instance.
**为何?**当不同的两个组件需要一个服务的不同的实例时,上面的方法这就不理想了。在这种情况下,我们最好在需要崭新和单独服务实例的组件里提供服务。
+makeTabs(
`style-guide/ts/07-03/app/app.component.ts,
style-guide/ts/07-03/app/heroes/hero-list/hero-list.component.ts`,
'',
`app/app.component.ts,
app/heroes/hero-list/hero-list.component.ts`)
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="07-04"></a>Use the @Injectable() Class Decorator
### <a id="07-04"></a>使用@Injectable()类装饰器
#### <a href="#07-04">Style 07-04</a>
#### <a href="#07-04">风格07-04</a>
.s-rule.do
:marked
**Do** use the `@Injectable` class decorator instead of the `@Inject` parameter decorator when using types as tokens for the dependencies of a service.
**坚持**当使用类型作为令牌来注入服务的依赖时,使用`@Injectable`类装饰器,而非`@Inject`参数装饰器。
.s-why
:marked
**Why?** The Angular DI mechanism resolves all the dependencies of our services based on their types declared with the services' constructors.
**为何?**Angular的依赖注入机制是根据在服务的构造函数里面的类型的声明来解析所有服务的依赖的。
.s-why.s-why-last
:marked
**Why?** When a service accepts only dependencies associated with type tokens, the `@Injectable()` syntax is much less verbose compared to using `@Inject()` on each individual constructor parameter.
**为何?**当服务只接受类型令牌相关的依赖时,比起在每个构造函数参数上使用`@Inject()``@Injectable()`的语法简洁多了。
+makeExample('style-guide/ts/07-04/app/heroes/shared/hero-arena.service.avoid.ts', 'example', 'app/heroes/shared/hero-arena.service.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/07-04/app/heroes/shared/hero-arena.service.ts', 'example', 'app/heroes/shared/hero-arena.service.ts')
:marked
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Data Services
## 数据服务
### <a id="08-01"></a>Separate Data Calls
### <a id="08-01"></a>分离数据调用
#### <a href="#08-01">Style 08-01</a>
#### <a href="#08-01">风格08-01</a>
.s-rule.do
:marked
**Do** refactor logic for making data operations and interacting with data to a service.
**坚持**把数据操作和数据互动重构到服务里。
.s-rule.do
:marked
**Do** make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations.
**坚持**让数据服务来负责XHR调用、本地储存、内存储存或者其他数据操作。
.s-why
:marked
**Why?** The component's responsibility is for the presentation and gathering of information for the view. It should not care how it gets the data, just that it knows who to ask for it. Separating the data services moves the logic on how to get it to the data service, and lets the component be simpler and more focused on the view.
**为何?**组件的职责是为视图展示或收集信息。它不应该理会如何得到数据,它只需要知道向谁要数据。把如何取得数据的逻辑移动到数据服务里,简化了组件,让其聚焦于视图。
.s-why
:marked
**Why?** This makes it easier to test (mock or real) the data calls when testing a component that uses a data service.
**为何?**在测试使用数据服务的组件时,可以让数据调用更容易被测试(模仿或者真实)。
.s-why.s-why-last
:marked
**Why?** Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as `Http`. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a component), also making it easier to change the implementation.
**为何?**数据服务的实现可能有非常具体的代码来处理数据仓库,包括数据头(headers)、如何与数据交谈或者其他服务(比如`Http`)。把逻辑分离到数据服务可以把该逻辑封装到一个地方,对外部使用者(比如组件)隐藏具体的实施细节。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
## Lifecycle Hooks
## 生命周期钩子
Use Lifecycle Hooks to tap into important events exposed by Angular.
使用生命周期钩子来介入到Angular暴露的重要事件里。
a(href="#toc") Back to top
.l-main-section
:marked
### <a id="09-01"></a>Implement Lifecycle Hooks Interfaces
### <a id="09-01"></a>实现生命周期钩子接口
#### <a href="#09-01">Style 09-01</a>
#### <a href="#09-01">风格09-01</a>
.s-rule.do
:marked
**Do** implement the lifecycle hook interfaces.
**坚持**实现生命周期钩子接口。
.s-why.s-why-last
:marked
**Why?** We avoid unintentionally not calling the hook if we misspell the method.
**为何?**避免在方法名字拼写错误时,造成无意间没有调用钩子的可能。
+makeExample('style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')(avoid=1)
:marked
+makeExample('style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')
:marked
a(href="#toc") Back to top
.l-main-section
:marked
## Appendix
## 附录
Useful tools and tips for Angular 2.
有用的Angular 2工具和小提示
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="A-01"></a>Codelyzer
### <a id="A-01"></a>Codelyzer
#### <a href="#A-01">Style A-01</a>
#### <a href="#A-01">风格A-01</a>
.s-rule.do
:marked
**Do** use [codelyzer](https://www.npmjs.com/package/codelyzer) to follow this guide.
**坚持**使用[codelyzer](https://www.npmjs.com/package/codelyzer)来实施本指南。
.s-rule.consider
:marked
**Consider** adjusting the rules in codelyzer to suit your needs.
**考虑**调整codelyzer的规则来满足你的需求。
a(href="#toc") Back to top
a(href="#toc") 回到顶部
.l-main-section
:marked
### <a id="A-02"></a>File Templates and Snippets
### <a id="A-02"></a>文档模板和代码片段
#### <a href="#A-02">Style A-02</a>
#### <a href="#A-02">风格A-02</a>
.s-rule.do
:marked
**Do** use file templates or snippets to help follow consistent styles and patterns. Here are templates and/or snippets for some of the web development editors and IDEs.
**坚持**使用文件模板或代码片段来帮助实现一致的风格和模式。下面是为一些网络开发编辑器和IDE准备的模板和/或代码片段:
.s-rule.consider
:marked
**Consider** using [snippets](https://atom.io/packages/angular-2-typescript-snippets) for [Atom](https://atom.io/) that follow these styles and guidelines.
**考虑** 使用[Atom](https://atom.io/)的[代码片段](https://atom.io/packages/angular-2-typescript-snippets)来实施本风格指南。
**Consider** using [snippets](https://github.com/orizens/sublime-angular2-snippets) for [Sublime Text](http://www.sublimetext.com/) that follow these styles and guidelines.
**考虑** 使用[Sublime Text](http://www.sublimetext.com/)的[代码片段](https://github.com/orizens/sublime-angular2-snippets)来实施本风格指南。
**Consider** using [snippets](https://github.com/mhartington/vim-angular2-snippets) for [Vim](http://www.vim.org/) that follow these styles and guidelines.
**考虑** 使用[Vim](http://www.vim.org/)的[代码片段](https://github.com/mhartington/vim-angular2-snippets)来实施本风格指南。
**Consider** using [snippets](https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2) for [Visual Studio Code](https://code.visualstudio.com/) that follow these styles and guidelines.
**考虑**使用[Visual Studio Code](https://code.visualstudio.com/)的[代码片段](https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2)来实施本风格指南。
<a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2">
<img src="https://github.com/johnpapa/vscode-angular2-snippets/raw/master/images/use-extension.gif", width="80%", alt="Use Extension">
</a>
a(href="#toc") Back to top
a(href="#toc") 回到顶部