Angular 有两种变更检测策略:Default
和OnPush
。在一些中小型项目中,直接使用默认的Default
策略即可,但如果在一些大型项目中,数据量比较大,而且变动比较频繁,一般会使用OnPush
策略来优化性能。
OnPush
策略提供了跳过对这个组件和它的所有子组件的不必要检查的可能性,以提高性能。
其中有一项很重要的就是输入的引用发生了变化。
JavaScript 中的所有东西都是通过引用传递的,但所有的基元(基础类型数据)都是不可改变的,它们的字面表述都指向同一个基元实例/引用。修改对象属性或数组条目不会创建一个新的引用,因此不会触发 OnPush 组件的变更检测。要触发变更检测器,你需要传递一个新的对象或数组引用来代替。
这就要求输入使用不可变
对象,每次对象属性发生变化都产生一个新对象引用,以便能够触发变更检测。
不可变对象
其实,要使用不可变对象,最简单的方式就是,每次当对象属性发生变化时,都重新生成一个新对象即可。像下面这样:
1 | let user = { |
相当于每次更改 user 对象都会重新生成一个新的对象。这样做的缺点就是,如果应用比较大,数据量比较大,会消耗更多的内存,而且降低性能。
immutable-js
Immutable-js是一个高性能的不可变
数据第三方库,是由 Facebook 开发维护的。
immutable-js
提供了很多结构,比如Record
,Map
, List
,Set
, Stack
等,一般我们常用的便是Map
和List
, Map
用以表示对象, List
用以表示数组,有多个对象。
在使用immutable-js
时,可以直接使用Map
模拟对象,像下面这样:
1 | const immutable = require("immutable"); |
也可以使用 Record
将对象包装一层,如下:
1 | import { Record } from "immutable"; |
使用 Record
的好处是,编辑器能通过类型分析,自动进行代码补全提示,像下面这样:
而直接使用 Map
却无法做到属性的自动补全提示。所以建议对于单个对象的提示,使用 Record
。
Angular 中使用 immutable
如上所述,Angular 中我们可以使用 Record
对对象包装一层,在组件中,使用不可变的 Record
, 监听事件里改的也是 Record
:
1 | // 定义User类 |
这样不管是在组件中,还是在模板中,都可以进行代码提示补全: