Immutable.js(持久化数据结构)
参考链接:https://zhuanlan.zhihu.com/p/101534155
实现的原理
持久化数据结构,数据一旦创建后无法被修改,任何变更都会生成新对象。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享
优势和劣势
优势:
-
结构共享:仅复制修改部分而非完整对象(通过 前缀树 复用未修改的部分)
- 减少内存占用
- 深拷贝的性能损耗
-
React 性能优化:Immutable天然支持浅比较
-
通过浅比较(
React.memo
、PureComponent
)快速判断组件是否需要重新渲染// 不可变数据更新前/后引用不同,浅比较即可检测变化 const prevState = { list: [1, 2, 3] }; const nextState = { ...prevState, list: [...prevState.list, 4] }; console.log(prevState === nextState); // false
-
Immutable.js
is()
方法,可以判断Immutable对象的内容是否相等,与useSelector
结合优化渲染import { useSelector, shallowEqual } from 'react-redux'; import { is } from 'immutable'; const userInfo = useSelector( state => state.getIn(['user', 'info']), (prev, next) => is(prev, next) // 仅当数据变化时触发重渲染 );
-
劣势:
- 增加学习成本,需要学习新API
- Immutable数据和 JS数据区分难。需引用TypeScript
- 调试更困难:控制台输出为嵌套结构,内部结构无法查看,需依赖JSON.stringify()输出,辅助调试
适用场景
React/Redux 状态管理、多线程数据共享、处理复杂数据/大数据集
Immutable.js 的几种数据类型
- List: 有序索引集,类似JavaScript中的Array。
- Map: 无序索引集,类似JavaScript中的Object。
- OrderedMap: 有序的Map,根据数据的set()进行排序。
- Set: 没有重复值的集合。
- OrderedSet: 有序的Set,根据数据的add进行排序。
- Stack: 有序集合,支持使用unshift()和shift()添加和删除。
- Record: 一个用于生成Record实例的类。类似于JavaScript的Object,但是只接收特定字符串为key,具有默认值。
- Seq: 序列,但是可能不能由具体的数据结构支持。
- Collection: 是构建所有数据结构的基类,不可以直接构建。
用的最多就是List和Map,所以在这里主要介绍这两种数据类型的API。
Immutable.js 的常用API
-
getIn(collection: unknown, keyPath: Iterable, notSetValue?: unknown),返回从提供的集合开始的提供的键路径处的值,如果未定义键路径,则返回 notSetValue
-
setIn(collection: C, keyPath: Iterable, value: unknown)
-
hasIn(collection: unknown, keyPath: Iterable),removeIn
-
is(xxx,xxx),判断是否对象值是否相等
-
get()、set()、update()、remove()、has()
-
fromJS(),将一个js数据转换为Immutable类型的数据
-
toJS(),将转换为Immutable类型数据 转 JS数据
替代方案参考
简单场景可选用 Immer(语法更友好)或 ES6 展开运算符(零依赖)
评论区