Angular的这10个特性,你可能不知道
图片 作者|angular-guru.com 译者|李志 大型框架 Angular 中隐藏着许多你可能不知道的有趣特性,本文介绍了其中 10 种。一起来看看吧! Angular 是一个大型框架,大多数人可能都用过其中的一小部分。但在它平凡的外表之下,隐藏着许多有用的特性,可以提高我们的工作效率。本文将介绍 Angular 的 10 种你可能没有听说过但却十分有用的特性。 Angular 中最容易被忽略却很有用的特性之一就是其提供的各种管道(pipe)。那么我们就先从这里讲起,来看看一些有用的管道吧!
1.KeyValuePipe
这是 Angluar 6.1 的主要特性之一。之前的 *ngFor 指令只允许你迭代数组或可迭代的结构体。如果想要迭代对象中的属性或 Map 中的项时,就会很麻烦。 这时,KeyValuePipe 就能帮我们大忙啦!我们只需将我们想要迭代的对象放到管道里,接下来的事就可以全权交给 *ngFor 处理了。例如:
@Component({
selector: 'app-list',
template: `
<ul>
<li *ngFor="let word of words | keyvalue">
{{ word.key }}: {{ word.value }}
</li>
</ul>
`
})
export class AppListComponent {
words = new Map([[1, 'Angular'], [2, 'Guru']]);
}
KeyValuePipe 的文档:https://angular.io/api/common/KeyValuePipe
2. 切片管道(Slice Pipe)
渲染一组项目并操作大量 DOM 节点通常是一个很耗资源的任务,因此有时我们希望减少需要显示的项目的数量。这种操作有许多实现方法,而 Angular 给出了一个十分简单的解决方案——SlicePipe,可作为 ngFor 表达式的一部分。 例如,我们想要显示一个数组中的前 10 项,就可以使用 SlicePipe 来完成。具体做法如下:
<ul>
<li *ngFor="let item of items | slice:0:10">{{ item }}</li>
</ul>
SlicePipe 文档:https://angular.io/api/common/SlicePipe
3. 小数管道(Decimal Pipe)
这是一个十分简单的管道,用于格式化数字,比如控制小数点后显示的数字个数。如果你比较喜欢让自己的数字的显示格式更容易阅读,比如每隔一个千位添加一个逗号(如 1000 显示为 1,000),也可以用这个管道来实现。 与这个管道相关的另一个特性是 formatNumber 函数,它是 @angular/common 的一部分,让你可以以编程的方式应用相同的格式,而不是在视图中使用管道。
<p>Your number is: {{ value | number }}</p>
DecimalPipe 的文档:https://angular.io/api/common/DecimalPipe formatNumber 的文档:https://angular.io/api/common/formatNumber
4. JSON 管道(JSON Pipe)
JSON 管道非常有用,尤其是在调试的时候。它可以让你在视图中以字符串的格式显示一个对象。比起在代码中打断点调试,这种方法更为简单易用。 JSON 管道的用法很简单,只需要将管道添加到你想要显示的对象后面即可。
<p>{{ myObj | json }}</p>
JsonPipe 文档: https://angular.io/api/common/JsonPipe 5. 标题和元服务 该特性在涉及搜索引擎和社交平台(如 Google、Twitter、Facebook 等)时尤其实用。这些平台会查找你页面上的< meta >标签用于描述页面内容,提供标题、描述、图像等等。 例如,下面这个博客的每篇博文都会有不同的标题、描述和图片。为保证每篇博文获得正确信息,我们可以使用元服务(meta service)。该服务允许我们动态添加和更新页面上的 meta 标签。具体做法如下:
export class AppComponent {
constructor(meta: Meta) {
// Twitter Markup
this.meta.updateTag({ name: 'twitter:card', content: 'summary_large_image' });
this.meta.updateTag({ name: 'twitter:site', content: '@TheAngularGuru' });
this.meta.updateTag({ name: 'twitter:title', content: 'Article title' });
this.meta.updateTag({ name: 'twitter:description', content: 'Article description' });
this.meta.updateTag({ name: 'twitter:image', content: 'image.jpg' });
}
}
另外,Angular 还提供了一个 Title 服务。也许你已经猜到,该服务的功能是更新浏览器窗口的标题。更新标题的通常做法是为文件头的< title >标签设置一个值,但这样我们就不能使用标准的 Angular 绑定(如<title>{{ myTitle }}</title>),因为< head >不属于 Angular 组件。因此,我们必须改用 Title 服务。该服务的使用方法极其简单:
export class AppComponent {
constructor(title: Title) {
title.setTitle('Window Title here');
}
}
Meta 的文档:https://angular.io/api/platform-browser/Meta Title 的文档:https://angular.io/api/platform-browser/Title
6. ng-container
你是否有过这样的经历:想要将两个结构指令放在一个元素里,搞了半天却发现并不能这样做…… 或者,你希望使用 ngTemplateOutlet 插入一个模板,结果发现插入的模板并不是子元素,而是变成了兄弟元素。 这非常糟心。因为你为了实现以上功能,需要添加一个随机的包裹< div >元素。而这种实现方法不仅不理想,还会污染你干净的 DOM 结构。 幸运的是,我们还有 ng-container 元素,可以避免上述问题。该元素只在开发过程中出现,实际上并不会在 DOM 上增加任何新元素,因此可以用来解决包括上述问题在内的很多问题。 例如,两个结构指令的问题可以用以下方式解决:
<ng-container *ngIf="condition">
<div *ngFor="let item of items">{{ item }}</div>
</ng-container>
插入模板作为子元素:
<div>
<ng-container [ngTemplateOutlet]="template"></ng-container>
</div>
上面两个例子只是该元素的诸多用法中的冰山一角。我相信你一定会发掘出它的更多应用!
7. 属性装饰器(Attribute Decorator)
我们都知道,@Input 和 @Output 是用来绑定和释放事件的属性装饰器。其实还有另一种比较小众的装饰器,@Attribute 装饰器。 这个装饰器在某些方面和 @Input 装饰器有点像,因为它可以用于向组件传递值。 这种属性绑定和 AngularJS 的字面量作用域(literal scope)绑定很像:
scope: {
type: '@'
}
- 首先我们来看一下这种绑定的不足之处:
- 所有值都是以字符串格式提供的
- 值是静态的,不能像绑定一样被更新
- 无法对其使用 [attribute] 绑定语法尽管有其局限性,如果我们不需要在意以上问题时,该方法还是能为我们提供很多方便,因为这些属性不属于绑定,在变更检测中不需要检查它们。 @Attribute 装饰器的使用方法和 @Input 装饰器相似:
@Attribute() type: string;
Attribute 指令的文档: https://angular.io/api/core/Attribute 更多内容还可参见这篇关于 Attribute 指令的文章:https://netbasal.com/getting-to-know-the-attribute-decorator-in-angular-4f7c9fb61243
8. 分析变更检测
我想大家一定都知道,在所有 Angular CLI 项目中,main.ts 文件都会调用 enableProdMode 函数。其实,该文件还可以调用 enableDebugMode 函数。你可能会想,如果代码不在生产模式下运行,一定是在调试模式下运行,但事实并非如此(至少在调用本函数时不是这样的)。 通过调用这个函数,我们在 window.ng 对象上会获得一个额外的工具,叫做 profiler。profiler 中有一个函数叫做 timeChangeDetection。当这个函数被调用时,会在控制台打印出变更检测的周期和每个周期的运行时间。 当需要分析性能较差的应用时,这个函数尤其有用。要调用这一函数,只需在引导代码中添加如下片段:
platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
const applicationRef = ref.injector.get(ApplicationRef);
const appComponent = applicationRef.components[0];
enableDebugTools(appComponent);
});
若要开始进行分析,只需在 DevTools 控制台上运行如下代码:
ng.profiler.timeChangeDetection();
9. NgPlural
在很多应用中,你可能需要描述一系列项目,而此时语言是个很麻烦的问题。比如,我们经常需要处理名词的单复数问题。例如,考虑如下三种情况:
- 列表中没有项(no items)
- 列表中有一个项(1 item)
- 列表中有两个项(2 items) 而针对这一情况,ngPlural 指令就是一个非常易用的处理方式。上面的例子可以用以下方式处理:
<p [ngPlural]="value">
<ng-template ngPluralCase="=0">There are no items</ng-template>
<ng-template ngPluralCase="=1">There is 1 item</ng-template>
<ng-template ngPluralCase="other">There are {{ value }} items</ng-template>
</p>
NgPlural 文档:https://angular.io/api/common/NgPlural NgPluralCase 文档:https://angular.io/api/common/NgPluralCase
10. ngPreserveWhitespaces 和 NgNonBindable
我把这两条指令放在一起来讲,因为在实际应用中,当需要对内容进行格式化时,这两条指令往往都会被用到。 在 Angular 5 中,angularCompilerOptions 里加入了 preserveWhitespaces 选项。如果该选项被设置为 false,编译器会移除所有不必要的空格。这对代码格式会有一些小小的影响,但却可以帮助我们缩小包的大小。 但是,有时候我们也希望完整地保留空格。如果希望整个组件保留其空格,只需要在组件装饰器中使用如下选项:
@Component({
selector: 'app',
templateUrl: './app.component.html',
preserveWhitespace: true
})
有时,我们可能只需要在某个特定的 DOM 元素中保留空格。这时,我们可以使用 ngPreserveWhitespaces 指令,如下所示:
<div ngPreserveWhitespaces>
<!-- All whitespace here will be preserved -->
</div>
另外,我们有时可能需要在文档中使用{{ }},但 Angular 会把这一符号看作插值,并会计算括号中内容的值。这时,可以将 ngNonBindable 指令插入父元素中,让 Angular 忽略其中的括号。示例用法如下:
<span ngNonBindable>{{ this will not be evaluated }}</span>
10 个你可能不知道的 Angular 特性已经介绍完毕,希望这些特性能够给你们带来帮助! 英文原文 https://angular-guru.com/blog/angular-unknown-features 课程推荐 推荐给你极客时间火爆专栏 --《深入拆解 Java 虚拟机》,作者为 Oracle Labs 高级研究员,已突破 1w+订阅。四大模块,覆盖 JVM 所有知识点,带你全方位拆解 JVM,系统学习 Java 性能分析、调优,掌握进阶必备技能! 扫码,即可试读此专栏的前三篇文章。