介绍
immer 是一个用于处理不可变数据的 JavaScript 库。它的核心概念是:通过创建新的数据对象来修改数据,而不是直接修改原始数据。
由来
在开发时,我们通常会通过修改数据来更新状态,但是js的对象是引用的,修改时,引用类型经常会产生一些无法意识到的副作用,例如创建一个Echarts的Options对象,同一个Options用于不同的图表,因为对象层级过深,容易导致修改之后应用于所有图表,从而导致数据错误。
const options = {
name: "折线图",
series: [],
xAxis: [],
yAxis: []
}
let chart1 = echarts.init(document.getElementById('chart1'));
options.name = "饼图";
chart1.setOption(options);
let chart2 = echarts.init(document.getElementById('chart2'));
// chart2的数据也会改变
chart2.setOption(options);传统上,一般使用深拷贝来解决这个问题,但是深拷贝会消耗大量内存,且效率较低。
let options1 = JSON.parse(JSON.stringify(options));
chart1.setOption(options);
let options2 = JSON.parse(JSON.stringify(options));
chart2.setOption(options);
// 或者使用lodash的cloneDeep
let options1 = _.cloneDeep(options);
chart1.setOption(options);
// chart2的数据不会改变
let options2 = _.cloneDeep(options);
chart2.setOption(options2);解决方案
通过immer,我们可以通过修改数据来更新状态,而不需要创建新的数据对象。同时,有比深拷贝更高的性能,且更简单
import { produce } from 'immer'
const options = {
name: "折线图",
series: [],
xAxis: [],
yAxis: []
}
let chart1 = echarts.init(document.getElementById('chart1'));
let options1 = produce(options, draft => {
draft.name = "饼图";
})
chart1.setOption(options1);
let chart2 = echarts.init(document.getElementById('chart2'));
// 核心代码,使用immer
let options2 = produce(options, draft => {
draft.name = "饼图2";
})
chart2.setOption(options2);优点
- 更加简单,使用起来更方便。
- 运行速度更快,因为不需要创建新的数据对象。
- 更加安全,因为 immer 会检查数据的变化,并确保数据的正确性。
- 兼容性更好,因为immer 支持所有 JavaScript 数据类型,包括对象、数组、Map、Set 等。
