菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
0
0

Angular 开发技巧

原创
05/13 14:22
阅读数 242

推荐课程:学习猿地精品在线课--前端开发工程师课程--点击进入

由于之前有幸去参加了 ngChina 2018 开发者大会,听了 will 保哥分享了 Angular 开发技巧,自己接触 Angular 也有差不多快一年的时间了,所以打算对 Angular 开发中的一些技巧做一个整理。

工具篇
所谓 “工欲善其事,必先利其器”,下面我会介绍 如何打磨 VS Code 这把利器。

1、抛弃”资源管理器“ ,使用快捷键Commd+P来查找文档,默认会展示最近打开的文档,并且支持模糊搜索文件。

2、快速打开最近文档:前进Ctrl+后退Ctrl-。

3、灵活使用 VS Code 重构功能,可以通过快捷键Command+对代码进行重构。

4、安装插件AngularExtensionPack(认准will保哥出品),这个插件集成了很多提升 Angular 开发效率的插件。比如:

在 TS 中使用 ng-import-* 导入常见的类。

模板编辑的时候实用 a-* 快速使用 Angular 的组件和指令(Angular v7 Snippets)。

使用 ng-* 来生成常用的ng代码段,创建 Component、Directive(Angular Snippets)等。

通过快捷键把 JSON 转换成 TS 类。

Ctrl+Alt+V 把粘贴板中的 JSON 转为 Typescript。

Ctrl+Alt+S 将选中的 JSON 生成对应的 Typescript,

还有一个值得一提的一个比较实用的功能,通过快捷键来 快速切换组件对应的不同的文件(Angular2-switcher):

还有很多其他功能,插件中有详细介绍:`Angular Extension Pack。

5、安装插件ClipboardHistory,这个插件会存储你最近的拷贝的记录,方便记录和粘贴最近几次的拷贝内容。

6、安装插件LocalHistory,这个插件用于维护文件的本地历史记录。每次修改文件时,旧内容的副本都会保留在本地历史记录中,你可以随时将文件与历史记录中的任何旧版本进行比较,如果发生意外时,可以帮助我们恢复丢失的内容,需要注意的是它会生成一个.history的文件夹进行本地修改的备份,所以我们需要再.gitignore排除这个文件夹,避免将其提交到 git 仓储。

7、安装插件Prettier-Codeformatter,这是一个代码格式化的插件,用过几个格式化的插件,个人感觉最好用的一个,更适合 Angular 开发。

8、安装 Chrome 插件AngularAngury进行调试工作,可以查看 Component 的 State、Router Tree、NgModules 的一些状态 (这个插件在复杂项目中并不是特别好用,包括对一些动态组件的支持比较差,但是在一些简单的项目中,或者新手在学习的时候安装这个插件比较方便调试排错)。

开发篇
下面会介绍一些 Angular 开发中的技巧。

1、使用模板语言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>

2、灵活使用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的方式则只需要进行一次维护。

3、使用ng-container对代码进行整理,使代码更清晰,提升代码的可读性。

        <ng-container *ngIf="type === 1">












         ...












        </ng-container>












        <ng-container *ngIf="type === 2">












         ...












        </ng-container>












        <ng-container *ngIf="type === 3">












         ...












        </ng-container>

4、@ViewChild读取指定类型的实例。

         <input #input thyInput [thyAutofocus]="true" />

上面这行代码有三个实例ElementRef、ThyInputComponent、ThyAutoFocusDirective,在某些情况下如果我们要获取指定类型的实例应该怎么做呢?

         @ViewChild('input', { read:ThyInputComponent })  inputComponent : ThyInputComponent;

5、使用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>

6、使用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();












         }

7、合理使用 ngZonerunOutsideAngular来提升应用性能

我们知道 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()主动触发变化检测。

8、灵活使用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 学习者提供帮助~

文章来自:http://www.ngui.cc/news/show-5865.html

发表评论

0/200
0 点赞
0 评论
收藏
为你推荐 换一批