相对于组件的路径

Write Component-Relative URLs to component templates and style files

为组件模板和样式表文件提供相对于组件的URL

Our components often refer to external template and style files. We identify those files with a URL in the templateUrl and styleUrls properties of the @Component metadata as seen here:

组件通常都是引用外部的模板和样式表文件。 我们在@Component的元数据中通过templateUrlstyleUrls属性来标识出它们的位置:

@Component({ selector: 'absolute-path', templateUrl: 'app/some.component.html', styleUrls: ['app/some.component.css'] })

By default, we must specify the full path back to the application root. We call this an absolute path because it is absolute with respect to the application root.

默认情况下,我们必须指定一个一直到应用程序根目录的完整路径。 我们称之为绝对路径,因为它绝对的以应用程序的根目录为基准。

There are two problems with an absolute path:

使用绝对路径有两个问题:

  1. We have to remember the full path back to the application root.

  2. 我们不得不记住到应用程序根目录的完整路径。

  3. We have to update the URL when we move the component around in the application files structure.

  4. 当我们在应用的文件结构中移动这个组件时,将不得不更新这个URL

It would be much easier to write and maintain our application components if we could specify template and style locations relative to their component class file.

如果能用相对于组件类文件的路径来指定模板和样式表的位置,那么编写和维护组件就会变得容易得多。

We can!

没问题!

We can if we build our application as commonjs modules and load those modules with a suitable package loader such as systemjs or webpack. Learn why below.

如果把应用构建成commonjs模块,并用一个合适的包加载器(比如systemjswebpack)加载那些模块,就可以用相对路径。 在下方可以学到原理。

The Angular CLI uses these technologies and defaults to the component-relative path approach described here. CLI users can skip this chapter or read on to understand how it works.

Angular CLI(命令行界面)使用这些技术,并默认采用这里所说的组件相对路径方法。 用CLI用户可以跳过本章,或者继续阅读来了解它是怎么工作的。

Component-Relative Paths

组件相对路径

Our goal is to specify template and style URLs relative to their component class files, hence the term component-relative path.

目标是把模板和样式表的URL指定为相对于组件类的路径,因此得名组件相对路径

The key to success is following a convention that puts related component files in well-known locations.

成功的关键是遵循一个约定:把相对组件的文件放进众所周知的位置。

We recommend keeping component template and component-specific style files as siblings of their companion component class files. Here we see the three files for SomeComponent sitting next to each other in the app folder.

建议把组件的模板和组件特有的样式表文件作为组件类文件的“兄弟”。 这里在app目录下依次有SomeComponent的三个文件。

app
some.component.css
some.component.html
some.component.ts
...

We'll have more files and folders — and greater folder depth — as our application grows. We'll be fine as long as the component files travel together as the inseparable siblings they are.

当应用规模增长后,还会有更多的文件和目录,目录深度也会增加。 如果组件的所有文件总是像形影不离的兄弟那样共进退,那该多好啊!

Set the moduleId

设置moduleId

Having adopted this file structure convention, we can specify locations of the template and style files relative to the component class file simply by setting the moduleId property of the @Component metadata like this

采用这种文件结构约定,可以为模板和样式表文件指定相对于组件类文件的位置 —— 只要简单的在@Component元数据中设置moduleId属性就可以了,就像这样:

moduleId: module.id,

We strip the app/ base path from the templateUrl and styleUrls. The result looks like this:

templateUrlstyleUrls中把基准路径app/去掉了。结果是这样的:

@Component({ moduleId: module.id, selector: 'relative-path', templateUrl: 'some.component.html', styleUrls: ['some.component.css'] })

Webpack users may prefer an alternative approach.

Webpack用户可能更喜欢一个替代方案

Source

源码

We can see the and download the source code from there or simply read the pertinent source here.

参见,并从中下载源码或只在这里阅读相关源码。

import { Component } from '@angular/core'; ///////// Using Absolute Paths /////// @Component({ selector: 'absolute-path', templateUrl: 'app/some.component.html', styleUrls: ['app/some.component.css'] }) export class SomeAbsoluteComponent { class = 'absolute'; type = 'Absolute template & style URLs'; path = 'app/path.component.html'; } ///////// Using Relative Paths /////// @Component({ moduleId: module.id, selector: 'relative-path', templateUrl: 'some.component.html', styleUrls: ['some.component.css'] }) export class SomeRelativeComponent { class = 'relative'; type = 'Component-relative template & style URLs'; path = 'path.component.html'; } <div class={{class}}> {{type}}<br>{{path}} </div> div.absolute { background: beige; border: 1px solid darkred; color: red; margin: 8px; max-width: 20em; padding: 4px; text-align: center; } div.relative { background: powderblue; border: 1px solid darkblue; color: Blue; font-style: italic; margin: 8px; max-width: 20em; padding: 4px; text-align: center; } import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `<h1>Absolute & <i>Component-Relative</i> Paths</h1> <absolute-path></absolute-path> <relative-path></relative-path> ` }) export class AppComponent {}

Appendix: why component-relative is not the default

附录:为什么组件相对路径不是默认方式

A component-relative path is obviously superior to an absolute path. Why did Angular default to the absolute path? Why do we have to set the moduleId? Why can't Angular set it?

组件相对路径明显比绝对路径高级一点。 为什么Angular默认采用了绝对路径呢? 为什么我们不得不设置moduleId呢?Angular为什么不能自己设置它?

First, let's look at what happens if we use a relative path and omit the moduleId.

首先,如果只使用相对路径而省略掉moduleId,我们来看看会发生什么。

EXCEPTION: Failed to load some.component.html

EXCEPTION: Failed to load some.component.html

Angular can't find the file so it throws an error.

Angular找不到这个文件,所以它抛出一个错误。

Why can't Angular calculate the template and style URLs from the component file's location?

为什么Angular不能相对于组件类文件的路径来自动计算模板和样式表的URL呢?

Because the location of the component can't be determined without the developer's help. Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or from CommonJS packages, to name a few. We might generate modules in any of several formats. We might not be writing modular code at all!

因为如果没有开发人员的帮助,组件的位置是检测不到的。 Angular应用可能被用多种方式加载:独立文件、SystemJS包、CommonJS包等等。 用来生成模块的格式可以是任何格式。 甚至可能完全没有写成模块化代码。

With this diversity of packaging and module load strategies, it's not possible for Angular to know with certainty where these files reside at runtime.

由于存在这么多打包和模块加载策略,所以Angular不可能知道在运行期这些文件的正确位置。

The only location Angular can be sure of is the URL of the index.html home page, the application root. So by default it resolves template and style paths relative to the URL of index.html. That's why we previously wrote our file URLs with an app/ base path prefix.

Angular能够确定的唯一的位置是首页index.html的URL,也就是应用的根目录。 所以,默认情况下,它只能计算相对于index.html的模板和样式表路径。 这就是为什么我们以前用app/基准路径的前缀来写文件的URL。

But if we follow the recommended guidelines and we write modules in commonjs format and we use a module loader that plays nice, then we — the developers of the application — know that the semi-global module.id variable is available and contains the absolute URL of the component class module file.

但是,如果遵循建议的指导原则,用commonjs格式编写模块,并使用一个不错的模块加载器, 我们要知道,有一个可用的半全局变量module.id,它包含组件类模块文件的绝对URL。

That knowledge enables us to tell Angular where the component file is by setting the moduleId:

这种认知让我们得以通过设置moduleId来告诉Angular组件类文件在哪里:

moduleId: module.id,

Webpack: load templates and styles

Webpack: 加载模板和样式表

Webpack developers have an alternative to moduleId.

Webpack开发者可以采用moduleId的另一个替代方案。

They can load templates and styles at runtime by adding ./ at the beginning of the template and styles / styleUrls properties that reference *component-relative URLS.

通过让组件元数据中的templatestyles / styleUrls属性以./开头,并使其指向相对于组件的URL,可以在运行期间为它们加载模板和样式表。

import { Component } from '@angular/core'; import '../../public/css/styles.css'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { }

Webpack will do a require behind the scenes to load the templates and styles. Read more here.

Webpack将会在幕后执行一次require来加载这些模板和样式。要了解更多,请参阅这里

See the Introduction to Webpack.

参见Webpack简介