因为以前有幸去参加了ngChina2018开发者大会,听了will保哥分享了Angular开发技巧,本身接触Angular也有差很少快一年的时间了,因此打算对Angular开发中的一些技巧作一个整理。
所谓 “工欲善其事,必先利其器”,下面我会介绍 如何打磨 `VS Code` 这把利器
复制代码
抛弃资源管理器
,使用快捷键 Commd + P
来查找文档,默认会展现最近打开的文档,而且支持模糊搜索文件node
快速打开最近文档:前进 Ctrl+➕
后退 Ctrl+➖
git
灵活使用VS Code重构功能,能够经过快捷键 Command +
对代码进行重构浏览器
安装插件 Angular Extension Pack
(认准will保哥出品),这个插件集成了不少提高Angular开发效率的插件,好比:bash
在 TS中实用 `ng-import-*` 导入常见的类
模板编辑的时候实用 ` a-*** ` 快速使用Angular的组件和指令 (Angular v7 Snippets)
实用 ` ng-* ` 来生成经常使用的ng代码段,建立 Component,Directive 等 (Angular Snippets)
复制代码
经过快捷键把JSON转换成TS类async
Ctrl+Alt+V 把粘贴板中的JSON 转为 Typescript
Ctrl+Alt+S 将选中的JSON 生成对应的 Typescript
复制代码
还有一个值得一提的一个比较实用的功能,经过快捷键来 快速切换组件对应的不一样的文件
(Angular2-switcher)ide
还有不少其余功能,插件中有详细介绍 `Angular Extension Pack工具
安装插件 Clipboard History
, 这个插件会存储你最近的拷贝的记录,方便记录和粘贴最近几回的拷贝内容性能
安装插件 Local History
,这个插件用于维护文件的本地历史记录。每次修改文件时,旧内容的副本都会保留在本地历史记录中,你能够随时将文件与历史记录中的任何旧版本进行比较,若是发生意外时,能够帮助咱们恢复丢失的内容,须要注意的是它会生成一个 .history
的文件夹进行本地修改的备份,因此咱们须要再 .gitignore
排除这个文件夹,避免将其提交到git仓储。学习
安装插件 Prettier - Code formatter
,这是一个代码格式化的插件,用过几个格式化的插件,我的感受最好用的一个,更适合Angular开发ui
安装 Chrome 插件 Angular Angury
进行调试工做,能够查看 Component 的 State,Router Tree,NgModules的一些状态 (这个插件在复杂项目中并非特别好用,包括对一些动态组件的支持比较差,可是在一些简单的项目中,或者新手在学习的时候安装这个插件比较方便调试排错)
下面会介绍一些Angular开发中的技巧
复制代码
使用模板语言 as
, 使用 as 对一些嵌套结构深的属性进行重命名
改进前:
<div *ngFor="let queue of fileUploadQueues">
<div class="icon" *ngIf="queue.result.file.icon">{{ queue.result.file.icon }}</div>
<div class="name" *ngIf="queue.result.file.name">{{ queue.result.file.name }}</div>
<div class="size" *ngIf="queue.result.file.size">{{ queue.result.file.size }}</div>
</div>
复制代码
改进后:
<div *ngFor="let queue of fileUploadQueues">
<ng-container *ngIf="queue.result.file as file">
<div class="icon" *ngIf="file.icon">{{ file.icon }}</div>
<div class="name" *ngIf="file.name">{{ file.name }}</div>
<div class="size" *ngIf="file.size">{{ file.size }}</div>
</ng-container>
</div>
复制代码
灵活使用 *ngIfElse
,不少人其实一直在写*ngIf
并不知道其实Angular支持 else
的写法 *ngIf="条件 ; else 模板"
,看看下面这两段代码
改进前:
<div *ngIf="(data$ | async).length > 0">
...
</div>
<div *ngIf="!(data$ | async).length > 0">
没有数据
</div>
复制代码
改进后:
<div *ngIf="(data$ | async).length > 0; else emptyTemplate;">
...
</div>
<ng-template #emptyTemplate>
没有数据
</ng-template>
复制代码
改进前的写法,也能实现一样的效果,可是由于数据是经过async
订阅的,第一种写法至关于进行了两次订阅,固然也能够用 as 来解决,这里只是一个示例。
还有一种状况,在条件多的时候,经过第一种方式写的话,若是条件有修改的话,必需要对取反后的条件进行维护, 而用 ngIfElse
的方式则只须要进行一次维护。
使用 ng-container
对代码进行整理,使代码更清晰,提高代码的可读性
<ng-container *ngIf="type === 1">
...
</ng-container>
<ng-container *ngIf="type === 2">
...
</ng-container>
<ng-container *ngIf="type === 3">
...
</ng-container>
复制代码
@ViewChild
读取指定类型的实例
<input #input thyInput [thyAutofocus]="true" />
复制代码
上面这行代码有三个实例 ElementRef
、ThyInputComponent
、ThyAutoFocusDirective
,在某些状况下若是咱们要获取指定类型的实例应该怎么作呢?
@ViewChild('input', { read:ThyInputComponent }) inputComponent : ThyInputComponent ;
复制代码
使用 async
管道,直接在模板中订阅流,而没必要将结果存储在中间属性中,当组件被销毁时,Angular将会自动取消订阅。
<div *ngFor="let item of data$ | async">
...
</div>
复制代码
在一些状况下,咱们可能须要重复使用订阅的数据,可是咱们又不能每次使用的时候都用 async
去订阅,因此咱们能够经过刚才说的 as
对齐进行重命名。
<div *ngFor="let item of data$ | async as data">
<span>一共有{{data.length}}条数据</span>
</div>
复制代码
使用 takeUntil
来管理订阅
在某些复杂的业务中,咱们可能须要订阅多个流,一个一个去取消订阅又繁琐,又会产生不少冗余代码,不利于代码的维护。这时候咱们能够takeUntil
来管理多个订阅,统一取消订阅。
private _ngUnsubscribe$ = new Subject();
ngOnInit() {
this.students$.pipe(
takeUntil(_ngUnsubscribe$)
).subscribe(() => {
...
});
this.books$.pipe(
takeUntil(_ngUnsubscribe$)
).subscribe(() => {
...
});
}
ngOnDestroy() {
this._ngUnsubscribe$.next();
this._ngUnsubscribe$.complete();
}
复制代码
合理使用 ngZone runOutsideAngular
来提高应用性能
咱们知道Angular能够自动处理变化检测,这是由于它使用了 zone.js
,简单的来讲,zone.js
就是经过打补丁的方式来拦截浏览器的事件,而后进行变化检测,可是变化检测是极其消耗资源的,若是绑定了大量的事件,那么就会形成性能问题,因此咱们可使用 runOutsideAngular
来减小没必要要的变化检测。
this.ngZone.runOutsideAngular(() => {
this.renderer.listen(this.elementRef.nativeElement, 'keydown', event => {
const keyCode = event.which || event.keyCode;
if (keyCode === keycodes.ENTER) {
event.preventDefault();
this.ngZone.run(() => {
this.thyEnter.emit(event);
});
}
});
});
复制代码
上面这段代码是绑定一个回车事件,若是不使用 runOutsideAngular
的话,只要触发键盘输入事件,就会执行变化检测,这时候咱们能够用 runOutsideAngular
在只有为enter事件的时候,去调用 ngZone.run()
主动触发变化检测
灵活使用 ngTemplateOutlet
来实现递归
<ng-container *ngFor="let node of treeNodes;" [ngTemplateOutlet]="nodeTemplate"
[ngTemplateOutletContext]="{node: node}">
</ng-container>
<ng-template #nodeTemplate let-node="node">
<div class='title'>{{node.title}}</div>
<ng-container *ngFor="let child of node?.children;" [ngTemplateOutlet]="nodeTemplate"
[ngTemplateOutletContext]="{node: child}">
</ng-container>
</ng-template>
复制代码
在咱们实际开发的过程当中,常常会展现一些树形结构的数据,若是业务场景比较简单,能够经过Angular的 ngTemplateOutlet
来实现递归展现,若是业务复杂,建议仍是经过组件的方式来实现。
上面是我这一年Angular开发的过程当中积累的一些小技巧(可能还有没想起来的,我想起来会慢慢的往上补),你们若是发现有错误的地方,请指正。其实去年就写好这篇文章,可是总感受缺点什么,不过无所谓了~~ 但愿能给Angular学习者提供帮助~
本文做者:王凯