在不改变原始数据的情况下,创建新的拷贝。
pnpm i immot
或者
yarn add immot
不可变数据
是函数式编程中极其重要的一个基本概念。React
的 state
设计为只读,即 不可变数据
,只能通过 setState
修改。此模块可以完美配合 React
,以简化 setState
操作不可变数据的繁琐步骤。
在 React
中,你不能这样做:
state.a.b.c = 1;
// or...
state.c.d.f.push(2);
通常,你会这样做:
const nextState = {
...state,
a: {
...state.a,
b: {
...state.a.b,
c: 1,
},
},
};
现在有了 immot
,让操作深层数据变得简单:
const nextState = $setIn(state, ['a', 'b', 'c'], 1);
nextState === state;
// false
注意 immot
不是深拷贝,深拷贝操作极其昂贵,无法适用于日常开发。immot
只会创建改变的数据,会引用原对象中未改变的部分。
immot
的 API 灵感来自于 immutable-js
,但 immutable-js
有独立的结构模型,复杂度高。immot
的设计理念是要求简单、易用,不需要过多的心智负担。因此在设计之初就亲和原生的 JSON
结构,只提供辅助函数,大小 < 1KB,就做到像 immutable-js
一样的效果。
immot
做到了 typescript
类型安全。$updateIn
、$setIn
、$mergeIn
中的 keyPath
路径支持类型自动提示(目前只支持小于 7 层结构)。
import * as immot from 'immot';
或者只导入其中某个函数
import { $updateIn } from 'immot';
immot
所有函数操作都会返回一个新的对象。
用于设置 对象/数组/Map
中的属性值。keyPath
为字符串。
const result = immot.$set(demo, 'a', 1);
用于设置 对象/数组/Map
中的属性值。它可以为深层对象做操作,keyPath
为路径数组
const result = immot.$setIn(demo, ['a', 'b', 1, 'c'], 'good');
用于合并 对象/数组
中的属性列表。
const result = immot.$merge(demo, { tom: 1, jack: 2 });
const result1 = immot.$merge(demo1, [5, 6]);
用于合并 对象/数组
中的属性列表。它可以为深层对象做操作,keyPath
为路径数组
const result = immot.$mergeIn(demo, ['a', 1, 'b'], { tom: 1, jack: 2 });
通过回调函数设置 对象/数组/Map
中的属性值。keyPath
为字符串。
const result = immot.$update(demo, 'money', (prev) => prev + 1);
通过回调函数设置 对象/数组/Map
中的属性值。它可以为深层对象做操作,keyPath
为路径数组
const result = immot.$updateIn(demo, ['todoList', 0, 'complete'], (complete) => !complete);
用于删除 对象/数组/Map
中的可选属性值,keyPath
为字符串或者数组
const result = immot.$delete(demo, 'a1');
const result1 = immot.$delete(demo, ['a1', 'a2']);
类似 Array.prototype.push
,但返回新数组
const result = immot.$push(demo, 4);
类似 Array.prototype.pop
,但返回新数组
const result = immot.$pop(demo);
类似 Array.prototype.shift
,但返回新数组
const result = immot.$shift(demo);
类似 Array.prototype.unshift
,但返回新数组
const result = immot.$unshift(demo, 4);
类似 Array.prototype.splice
,但返回新数组
const result = immot.$splice(demo, 1, 0, 'test');
在 /bench
目录中有性能测试对比的样例,可以 clone 本项目测试
cd bench
pnpm i
node index.mjs
注意:
- 数值为每秒操作数量,越高越好
- 样例中
immer
关闭了自动冻结对象的特性,否则结果会更差。 - 数组性能测试图中隐藏了
immutableJS
数据,用空间换取时间的方式导致数值太高,影响对比。
在 Node v14.17.0 的测试结果: