@xuemingdeng
2018-08-15T07:35:51.000000Z
字数 5318
阅读 3275
作者:angular-guru.com
译者:李志
摘要:大型框架Angular中隐藏着许多你可能不知道的有趣特性,本文介绍了其中10种。一起来看看吧!
Angular是一个大型框架,大多数人可能都用过其中的一小部分。但在它平凡的外表之下,隐藏着许多有用的特性,可以提高我们的工作效率。本文将介绍Angular的10种你可能没有听说过但却十分有用的特性。
Angular中最容易被忽略却很有用的特性之一就是其提供的各种管道(pipe)。那么我们就先从这里讲起,来看看一些有用的管道吧!
这是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
渲染一组项目并操作大量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
这是一个十分简单的管道,用于格式化数字,比如控制小数点后显示的数字个数。如果你比较喜欢让自己的数字的显示格式更容易阅读,比如每隔一个千位添加一个逗号(如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
JSON管道非常有用,尤其是在调试的时候。它可以让你在视图中以字符串的格式显示一个对象。比起在代码中打断点调试,这种方法更为简单易用。
JSON管道的用法很简单,只需要将管道添加到你想要显示的对象后面即可。
<p>{{ myObj | json }}</p>
JsonPipe文档见https://angular.io/api/common/JsonPipe
该特性在涉及搜索引擎和社交平台(如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
你是否有过这样的经历:想要将两个结构指令放在一个元素里,搞了半天却发现并不能这样做……
或者,你希望使用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>
上面两个例子只是该元素的诸多用法中的冰山一角。我相信你一定会发掘出它的更多应用!
我们都知道,@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
我想大家一定都知道,在所有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();
在很多应用中,你可能需要描述一系列项目,而此时语言是个很麻烦的问题。比如,我们经常需要处理名词的单复数问题。例如,考虑如下三种情况:
而针对这一情况,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
我把这两条指令放在一起来讲,因为在实际应用中,当需要对内容进行格式化时,这两条指令往往都会被用到。
在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特性已经介绍完毕,希望这些特性能够给你们带来帮助!