parent
5aeb397489
commit
d79eab8641
|
@ -433,7 +433,7 @@ a#input
|
|||
and we are binding that `color` to the directive.
|
||||
We should expect to find a `color` on the host `AppComponent`.
|
||||
|
||||
眼光锐利的你可能发现了,模板中的单选按钮的点击事件处理器设置了一个`color`属性,而且我们把`color`绑定到了我们的指令上。
|
||||
眼尖的读者可能发现了,模板中的单选按钮的点击事件处理器设置了一个`color`属性,而且我们把`color`绑定到了我们的指令上。
|
||||
我们会期望在这个宿主`AppComponent`上发现一个`color`属性。
|
||||
|
||||
**We never defined a color property for the host *AppComponent***!
|
||||
|
|
|
@ -28,7 +28,7 @@ block includes
|
|||
* [Loading Styles into Components](#loading-styles)
|
||||
* [把样式加载进组件](#loading-styles)
|
||||
* [Controlling View Encapsulation: Emulated, Native, and None](#view-encapsulation)
|
||||
* [控制视图的包装方式:模拟(Emulated)、原生(Native)或无(None)](#view-encapsulation)
|
||||
* [控制视图的包装模式:仿真(Emulated)、原生(Native)或无(None)](#view-encapsulation)
|
||||
* [Appendix 1: Inspecting the generated runtime component styles](#inspect-generated-css)
|
||||
* [附录1: 审查生成的运行时组件样式](#inspect-generated-css)
|
||||
* [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
|
||||
|
@ -110,7 +110,7 @@ a(id="special-selectors")
|
|||
Component styles have a few special *selectors* from the world of
|
||||
[shadow DOM style scoping](https://www.w3.org/TR/css-scoping-1):
|
||||
|
||||
“组件样式”中有一些特殊的*选择器*,它们是从[范围化CSS](https://www.w3.org/TR/css-scoping-1)的世界里引入的shadow DOM选择器。
|
||||
“组件样式”中有一些特殊的*选择器*,它们是从[局限化CSS](https://www.w3.org/TR/css-scoping-1)的世界里引入的Shadow DOM(影子DOM)选择器。
|
||||
|
||||
### :host
|
||||
### :host
|
||||
|
@ -197,8 +197,8 @@ a(id="special-selectors")
|
|||
[Controlling View Encapsulation](#view-encapsulation)
|
||||
section for more details.
|
||||
|
||||
`/deep/`和`>>>`选择器只能被用在**模拟(Emulated)**视图包装方式下。
|
||||
这种方式是默认值,也是用得最多的方式。要了解更多,请参阅[控制视图包装方式](#view-encapsulation)一节。
|
||||
`/deep/`和`>>>`选择器只能被用在**仿真(Emulated)**模式下。
|
||||
这种方式是默认值,也是用得最多的方式。要了解更多,请参阅[控制视图包装模式](#view-encapsulation)一节。
|
||||
|
||||
a(id='loading-styles')
|
||||
.l-main-section
|
||||
|
@ -218,7 +218,7 @@ a(id='loading-styles')
|
|||
|
||||
The scoping rules outlined above apply to each of these loading patterns.
|
||||
|
||||
上述范围化规则对所有这些加载模式都适用。
|
||||
上述局限化规则对所有这些加载模式都适用。
|
||||
|
||||
### Styles in Metadata
|
||||
### 元数据中的样式
|
||||
|
@ -275,6 +275,8 @@ block module-bundlers
|
|||
|
||||
像Webpack这类模块打包器的用户可能会使用`styles`属性来在构建时从外部文件中加载样式。他们可能这样写:
|
||||
|
||||
`styles: [require('my.component.css')]`
|
||||
|
||||
`styles: [require('my.component.css')]`
|
||||
|
||||
We set the `styles` property, **not** `styleUrls` property! The module
|
||||
|
@ -292,23 +294,33 @@ block module-bundlers
|
|||
|
||||
:marked
|
||||
### Template Link Tags
|
||||
### 模板中的link标签
|
||||
|
||||
We can also embed `<link>` tags into the component's HTML template.
|
||||
|
||||
我们也可以在组件的HTML模板中嵌入`<link>`标签。
|
||||
|
||||
As with `styleUrls`, the link tag's `href` URL is relative to the
|
||||
application root, not relative to the component file.
|
||||
|
||||
像`styleUrls`标签一样,这个link标签的`href`指向的URL也是相对于应用的根目录的,而不是组件文件。
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-team.component.ts', 'stylelink')
|
||||
|
||||
:marked
|
||||
### CSS @imports
|
||||
### CSS @imports
|
||||
|
||||
We can also import CSS files into our CSS files by using the standard CSS
|
||||
[`@import` rule](https://developer.mozilla.org/en/docs/Web/CSS/@import).
|
||||
|
||||
我们还可以利用标准的CSS[`@import`规则](https://developer.mozilla.org/en/docs/Web/CSS/@import)来把其它CSS文件导入到我们的CSS文件中。
|
||||
|
||||
block css-import-url
|
||||
:marked
|
||||
In *this* case the URL is relative to the CSS file into which we are importing.
|
||||
|
||||
在*这种*情况下,URL是相对于我们执行导入操作的CSS文件的。
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'import', 'app/hero-details.component.css (excerpt)')
|
||||
|
||||
|
@ -316,29 +328,45 @@ a#view-encapsulation
|
|||
.l-main-section
|
||||
:marked
|
||||
## Controlling View Encapsulation: Native, Emulated, and None
|
||||
## 控制视图的包装模式:原生(Native),仿真(Emulated)和无(None)
|
||||
|
||||
As discussed above, component CSS styles are *encapsulated* into the component's own view and do
|
||||
not affect the rest of the application.
|
||||
|
||||
像上面讨论过的一样,组件的CSS样式被包装进了自己的视图中,而不会影响到应用程序的其它部分。
|
||||
|
||||
We can control how this encapsulation happens on a *per
|
||||
component* basis by setting the *view encapsulation mode* in the component metadata. There
|
||||
are three modes to choose from:
|
||||
|
||||
通过在组件的元数据上设置*视图包装模式*,我们可以分别控制*每个组件*的包装模式。
|
||||
可选的包装模式一共有三种:
|
||||
|
||||
* `Native` view encapsulation uses the browser's native [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
||||
implementation to attach a Shadow DOM to the component's host element, and then puts the component
|
||||
view inside that Shadow DOM. The component's styles are included within the Shadow DOM.
|
||||
* `Native`模式使用浏览器原生的[Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
||||
实现来为组件的宿主元素附加一个Shadow DOM。组件的样式被包裹在这个Shadow DOM中。
|
||||
|
||||
* `Emulated` view encapsulation (**the default**) emulates the behavior of Shadow DOM by preprocessing
|
||||
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
||||
See [Appendix 1](#inspect-generated-css) for details.
|
||||
|
||||
* `Emulated`模式(**默认值**)通过预处理(并改名)CSS代码来仿真Shadow DOM的行为,以达到把CSS样式局限在组件视图中的目的。
|
||||
参见[附录1](#inspect-generated-css)了解详情。
|
||||
|
||||
* `None` means that Angular does no view encapsulation.
|
||||
Angular adds the CSS to the global styles.
|
||||
The scoping rules, isolations, and protections discussed earlier do not apply.
|
||||
This is essentially the same as pasting the component's styles into the HTML.
|
||||
* `None`意味着Angular不使用视图包装。
|
||||
Angular会把CSS添加到全局样式中。而不会应用上前面讨论过的那些局限化规则、隔离和保护等规则。
|
||||
从本质上来说,这跟把组件的样式直接放进HTML是一样的。
|
||||
|
||||
Set the components encapsulation mode using the `encapsulation` property in the component metadata:
|
||||
|
||||
通过组件元数据中的`encapsulation`属性来设置组件包装模式:
|
||||
|
||||
+makeExample('component-styles/ts/app/quest-summary.component.ts', 'encapsulation.native')(format='.')
|
||||
|
||||
:marked
|
||||
|
@ -346,19 +374,27 @@ a#view-encapsulation
|
|||
for Shadow DOM](http://caniuse.com/#feat=shadowdom). The support is still limited,
|
||||
which is why `Emulated` view encapsulation is the default mode and recommended
|
||||
in most cases.
|
||||
|
||||
原生(`Native`)模式只适用于[有原生Shadow DOM支持的浏览器](http://caniuse.com/#feat=shadowdom)。
|
||||
因此仍然受到很多限制,这就是为什么我们会把仿真(`Emulated`)模式作为默认选项,并建议将其用于大多数情况。
|
||||
|
||||
a#inspect-generated-css
|
||||
.l-main-section
|
||||
:marked
|
||||
## Appendix 1: Inspecting The CSS Generated in Emulated View Encapsulation
|
||||
## 附录1:查看仿真(Emulated)模式下生成的CSS
|
||||
|
||||
When using the default emulated view encapsulation, Angular preprocesses
|
||||
all component styles so that they approximate the standard Shadow CSS scoping rules.
|
||||
|
||||
当使用默认的“仿真”模式时,Angular会对组件的所有样式进行预处理,让它们模仿出标准的Shadow CSS局限化规则。
|
||||
|
||||
When we inspect the DOM of a running Angular application with emulated view
|
||||
encapsulation enabled, we see that each DOM element has some extra attributes
|
||||
attached to it:
|
||||
|
||||
当我们查看启用了“仿真”模式的Angular应用时,我们看到每个DOM元素都被加上了一些额外的Attribute。
|
||||
|
||||
code-example(format="").
|
||||
<hero-details _nghost-pmm-5>
|
||||
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
||||
|
@ -369,16 +405,26 @@ code-example(format="").
|
|||
|
||||
:marked
|
||||
We see two kinds of generated attributes:
|
||||
|
||||
我们看到了两种被生成的Attribute:
|
||||
* An element that would be a Shadow DOM host in native encapsulation has a
|
||||
generated `_nghost` attribute. This is typically the case for component host elements.
|
||||
|
||||
* 如果一个元素在原生包装方式下将成为Shadow DOM的宿主,那么它将被自动添加上一个`_nghost` Attribute。
|
||||
这是组件宿主元素的典型情况。
|
||||
|
||||
* An element within a component's view has a `_ngcontent` attribute
|
||||
that identifies to which host's emulated Shadow DOM this element belongs.
|
||||
|
||||
* 组件视图中的每一个元素,都有一个`_ngcontent`属性,它会标记出这个元素属于哪个Shadow DOM宿主。
|
||||
|
||||
The exact values of these attributes are not important. They are automatically
|
||||
generated and we never refer to them in application code. But they are targeted
|
||||
by the generated component styles, which we'll find in the `<head>` section of the DOM:
|
||||
|
||||
这些属性的精确值并不重要。它们是自动生成的,并且我们永远不会在程序代码中直接引用到它们。
|
||||
但它们会作为生成的组件样式的目标,就像我们在DOM的`<head>`区所看到的:
|
||||
|
||||
code-example(format="").
|
||||
[_nghost-pmm-5] {
|
||||
display: block;
|
||||
|
@ -395,15 +441,23 @@ code-example(format="").
|
|||
with `_nghost` or `_ngcontent` attribute selectors.
|
||||
These extra selectors enable the scoping rules described in this guide.
|
||||
|
||||
这些就是我们写的那些样式被处理后的结果,于是每个选择器都被增加了`_nghost`或`_ngcontent`属性选择器。
|
||||
在这些附加选择器的帮助下,我们实现了本指南中所描述的这些局限化规则。
|
||||
|
||||
We'll likely live with *emulated* mode until shadow DOM gains traction.
|
||||
|
||||
小伙伴儿们会很愉快的使用*仿真*模式 —— 直到有一天Shadow DOM获得全面支持。
|
||||
|
||||
a#relative-urls
|
||||
.l-main-section
|
||||
:marked
|
||||
## Appendix 2: Loading Styles with Relative URLs
|
||||
## 附录2:使用相对URL加载样式
|
||||
|
||||
It's common practice to split a component's code, HTML, and CSS into three separate files in the same directory:
|
||||
|
||||
把组件的代码(ts/js)、HTML和CSS分别放到同一个目录下的三个不同文件,是一个常用的实践:
|
||||
|
||||
code-example(format='').
|
||||
quest-summary.component.ts
|
||||
quest-summary.component.html
|
||||
|
@ -413,54 +467,96 @@ code-example(format='').
|
|||
We include the template and CSS files by setting the `templateUrl` and `styleUrls` metadata properties respectively.
|
||||
Because these files are co-located with the component,
|
||||
it would be nice to refer to them by name without also having to specify a path back to the root of the application.
|
||||
|
||||
我们会通过设置元数据的`templateUrl`和`styleUrls`属性把模板和CSS文件包含进来。
|
||||
既然这些文件都与组件(代码)文件放在一起,那么通过名字,而不是到应用程序根目录的全路径来指定它,就会是一个漂亮的方式。
|
||||
|
||||
block module-id
|
||||
:marked
|
||||
We'd *prefer* to write this:
|
||||
|
||||
我们期望的*首选*方式是这样写:
|
||||
|
||||
+makeExample('component-styles/ts/app/quest-summary.component.ts', 'urls')(format='.')
|
||||
|
||||
:marked
|
||||
We can't do that by default. Angular can't find the files and throws an error:
|
||||
|
||||
但默认情况下我们不能这么做。Angular找不到这个文件,并且抛出一个错误:
|
||||
|
||||
`EXCEPTION: Failed to load quest-summary.component.html`
|
||||
|
||||
|
||||
`异常:不能加载quest-summary.component.html文件(EXCEPTION: Failed to load quest-summary.component.html)`
|
||||
|
||||
Why can't Angular calculate the HTML and CSS URLs from the component file's location?
|
||||
|
||||
为什么Angular不能根据组件文件的位置计算出HTML和CSS文件的URL呢?
|
||||
|
||||
Unfortunately, that location is not readily known.
|
||||
Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or
|
||||
from CommonJS packages, to name a few.
|
||||
With this diversity of load strategies, it's not easy to tell at runtime where these files actually reside.
|
||||
|
||||
很不幸,当前的位置并不是已知的。
|
||||
Angular应用可以用多种方式被加载:从独立的文件、从SystemJS包,或从CommonJS包等等。
|
||||
由于存在这么多种加载策略,要想在运行期知道这些文件的实际位置,可不是一件容易的事。
|
||||
|
||||
The only location Angular can be sure of is the URL of the `index.html` home page.
|
||||
So by default it resolves template and style paths relative to the URL of `index.html`.
|
||||
That's why we previously wrote our CSS file URLs with an `app/` base path prefix.
|
||||
|
||||
Angular唯一能够确定的位置,就是起始页`index.html`的URL。
|
||||
所以,默认情况下,它都是以`index.html`的URL为基准来计算模板和样式的相对路径的。
|
||||
这就是为什么我们以前写自身CSS文件的URL都以`app/`基本路径作为前缀。
|
||||
|
||||
Although this works with any code loading scheme, it is very inconvenient.
|
||||
We move file folders around all the time during the evolution of our applications.
|
||||
It's no fun patching the style and template URLs when we do.
|
||||
|
||||
虽然这能够和各种代码加载方案协同工作,但它很不方便。
|
||||
在应用程序的进化过程中,我们经常要移动文件夹。整天被迫修改样式和模板的URL可一点儿都不好玩儿!
|
||||
|
||||
### *moduleId*
|
||||
### *moduleId*
|
||||
|
||||
We can change the way Angular calculates the full URL be setting the component metadata's `moduleId` property.
|
||||
|
||||
我们可以通过设置组件元数据中的`moduleId`属性,我们可以改变Angular计算完整URL的方式。
|
||||
|
||||
If we knew the component file's base path, we'd set `moduleId` to that and
|
||||
let Angular construct the full URL from this base path plus the CSS and template file names.
|
||||
|
||||
如果我们知道组件文件的基本路径,我们就可以把`moduleId`设置成它,
|
||||
让Angular可以用这个基本路径加上CSS和模板文件的名字来构造出完整URL。
|
||||
|
||||
Our challenge is to calculate the base path with minimal effort.
|
||||
If it's too hard, we shouldn't bother; we should just write the full path to the root and move on.
|
||||
Fortunately, *certain* module loaders make it relatively easy to find the base path.
|
||||
|
||||
我们的挑战是如何用最小的代价计算出这个基本路径。
|
||||
如果太难,我们也不想自找麻烦,还不如直接写到程序根目录的全路径,然后继续。
|
||||
幸运的是,在*某些*模块加载器中找到基本路径要相对简单一些。
|
||||
|
||||
SystemJS (starting in v.0.19.19) sets a *semi-global* variable to the URL of the component file.
|
||||
That makes it trivial to set the component metadata `moduleId` property to the component's URL
|
||||
and let Angular determine the module-relative paths for style and template URLs from there.
|
||||
|
||||
SystemJS(自从v.0.19.19起)设置了一个*半全局*变量来指向组件文件的URL。
|
||||
有了它,把组件元数据的`moduleId`属性设置为组件本身的URL就简单多了,
|
||||
这样Angular就能让样式和模板的URL使用相对于模块的路径。
|
||||
|
||||
The name of the *semi-global* variable depends upon whether we told TypeScript to transpile to
|
||||
'system' or 'commonjs' format (see the `module` option in the
|
||||
[TypeScript compiler documentation](http://www.typescriptlang.org/docs/handbook/compiler-options.html)).
|
||||
The variables are `__moduleName` and `module.id` respectively.
|
||||
|
||||
这个*半全局*变量的名字取决于我们是告诉TypeScript转译成'system'还是'commonjs'格式
|
||||
(参见[TypeScript编译器文档](http://www.typescriptlang.org/docs/handbook/compiler-options.html)中的`module`选项)。
|
||||
这个变量分别是`__moduleName`(system格式)和`module.id`(commonjs格式)。
|
||||
|
||||
Here's an example in which we set the metadata `moduleId` to `module.id`.
|
||||
|
||||
下面的例子中示范了我们如何把元数据中的`moduleId`设置为`module.id`。
|
||||
|
||||
+makeExample('component-styles/ts/app/quest-summary.component.ts','', 'app/quest-summary.component.ts')
|
||||
|
||||
|
@ -468,3 +564,5 @@ block module-id
|
|||
:marked
|
||||
With a module bundler like Webpack we are more likely to set the `styles` and `template` properties with the bundler's
|
||||
`require` mechanism rather than bother with `styleUrls` and `templateUrl`.
|
||||
|
||||
如果使用像Webpack这样的模块打包器,我们更喜欢借助打包器本身的`require`机制来设置`styles`和`template`属性,而不是`styleUrls`和`templateUrl`。
|
||||
|
|
|
@ -48,7 +48,7 @@ include ../_util-fns
|
|||
|
||||
- displaying validation errors to users and enable/disable form controls
|
||||
|
||||
- 向用户显示有效性验证的错误提示,以及禁用/使能表单控件
|
||||
- 向用户显示有效性验证的错误提示,以及禁用/启用表单控件
|
||||
|
||||
- sharing information among controls with template reference variables
|
||||
|
||||
|
@ -80,7 +80,7 @@ include ../_util-fns
|
|||
conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.
|
||||
|
||||
我们可以构建要用在Angular模板中的几乎所有表单 —— 登录表单、联系人表单…… 大量的各种商务表单。
|
||||
我们可以创造性的摆放各种控件、把它们绑定到数据、指定校验规则、显示校验错误、有条件的禁用/使能特定的控件、触发内置的视觉反馈等等,不胜枚举。
|
||||
我们可以创造性的摆放各种控件、把它们绑定到数据、指定校验规则、显示校验错误、有条件的禁用/启用特定的控件、触发内置的视觉反馈等等,不胜枚举。
|
||||
|
||||
It will be pretty easy because Angular handles many of the repetitive, boiler plate tasks we'd
|
||||
otherwise wrestle with ourselves.
|
||||
|
@ -1073,7 +1073,7 @@ figure.image-display
|
|||
Not impressed? Think about it for a moment. What would we have to do to
|
||||
wire the button's enable/disabled state to the form's validity without Angular's help?
|
||||
|
||||
没想明白?再想一会儿。如果没有Angular `NgForm`的帮助,我们又该怎么让按钮的禁用/使能状态和表单的有效性关联起来呢?
|
||||
没想明白?再想一会儿。如果没有Angular `NgForm`的帮助,我们又该怎么让按钮的禁用/启用状态和表单的有效性关联起来呢?
|
||||
|
||||
For us, it was as simple as
|
||||
|
||||
|
|
Loading…
Reference in New Issue