DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师。
官方网站:devui.design
Ng组件库:ng-devui(欢迎Star)
引言
Angular 框架作为前端三大框架之一,有着其独到优点,可用于创建高效、复杂、精致的单页面应用。
本文介绍了Angular开发过程中推荐的十八个最佳实践及示例,用于开发过程中参考运用。
1. trackBy
What
当使用*ngFor指令在html中对数组进行陈列时,添加trackBy()函数,目的是为每个item指定一个独立的id
Why
一般情况下,当数组内有变更时,Angular将会对整个DOM树加以重新渲染。如果加上trackBy方法,Angular将会知道具体的变更元素,并针对性地对此特定元素进行DOM刷新,提升页面渲染性能
详细内容 -> NetanelBasal
Example
【Before】
<li *ngFor="let item of items;">{
{ item }}</li>
【After】
// in the template <li *ngFor="let item of items; trackBy: trackByFn">{ { item }}</li> // in the component trackByFn(index, item) { return item.id; // unique id corresponding to the item }
2. const vs let
What
声明常量时,使用const而不是let
Why
a. 使赋值意图更加明确
b. 若常量被重赋值,编译将直接报错,避免潜在风险
c. 增加代码可读性
Example
【Before】
let car = 'ludicrous car';
let myCar = `My ${car}`;
let yourCar = `Your ${car};
if (iHaveMoreThanOneCar) {
myCar = `${myCar}s`;
}
if (youHaveMoreThanOneCar) {
yourCar = `${youCar}s`;
}
【After】
// 变量car不会被重赋值,所以用const声明
const car = 'ludicrous car';
let myCar = `My ${car}`;
let yourCar = `Your ${car};
if (iHaveMoreThanOneCar) {
myCar = `${myCar}s`;
}
if (youHaveMoreThanOneCar) {
yourCar = `${youCar}s`;
}
3. pipeable 操作符
What
使用RxJs算子时,使用pipeable操作符号 -> 拓展阅读
Why
a. 可被摇树优化: import的代码中,只有需要被执行的才会被引入
b. 容易定位到代码中未使用的算子
注: 需要RxJs版本在5.5及以上
Example
【Before】
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';
iAmAnObservable
.map(value => value.item)
.take(1)
【After】
import { map, take } from 'rxjs/operators';
iAmAnObservable
.pipe(
map(value => value.item),
take(1)
)
4. 隔离API攻击
What
不是所有的API都是安全的 -> 很多情况下需要添加额外的代码逻辑去为API打补丁
相较于将这些逻辑放在component中,更好的做法是封装到一个独立的地方:比如封装到service中,再在其他地方引用
Why
a. 隔离攻击,使得攻击更靠近于原有的请求所在地
b. 减少用于处理攻击打补丁的代码
c. 将这些攻击封装在同一个地方,更容易发现
d. 当要解决bug的时候, 只需要到同一个文件内去搜寻,更容易定位
注: 也可以打个自有标签,比如API_FIX
,类似于TODO
标签,用于标记API修复
5. 模板的订阅
What
最好在html订阅变化,而不是在ts中
Why
a. async
管道能自动取消订阅:通过减少手动订阅管理能够简化代码
b. 减少在ts中忘记取消订阅,造成内存泄露的风险(这种风险也可以通过lint规则检测来避免)
c. 减少由于在订阅之外数据发生变更,进而引入bug的情况
Example
【Before】
// template
<p>{
{ textToDisplay }}</p>
// component
iAmAnObservable
.pipe(
map(value => value.item),
takeUntil(this._destroyed$)
)
.subscribe(item => this.textToDisplay = item
【After】
// template
<p>{
{ textToDisplay$ | async }}</