Immutable 在 React 中的应用
理解 Immutable 数据结构及其在 React 项目中的使用方式
问题
如何理解 Immutable?如何在 React 项目中应用?
解答
什么是 Immutable
Immutable 指一旦创建就不能被更改的数据。对 Immutable 对象的任何修改、添加或删除操作都会返回一个新的 Immutable 对象。
Immutable 基于 Persistent Data Structure(持久化数据结构)实现。当数据被修改时,会返回一个新对象,但新对象会尽可能复用之前的数据结构,避免内存浪费。
通过 Structural Sharing(结构共享),当对象树中某个节点发生变化时,只修改该节点和受影响的父节点,其他节点保持共享。
使用 immutable.js
immutable.js 提供了完整的不可变数据结构,主要数据类型包括:
- List:有序索引集,类似 Array
- Map:无序索引集,类似 Object
- Set:无重复值的集合
常用方法:
import Immutable, { Map, is } from 'immutable';
// fromJS:将 JS 数据转换为 Immutable 类型
const obj = Immutable.fromJS({ a: '123', b: '234' });
// toJS:将 Immutable 数据转换为 JS 类型
const jsObj = obj.toJS();
// is:比较两个对象
const map1 = Map({ a: 1, b: 1, c: 1 });
const map2 = Map({ a: 1, b: 1, c: 1 });
map1 === map2; // false
is(map1, map2); // true
// get:取值
obj.get('a');
// getIn:嵌套取值
let abs = Immutable.fromJS({ a: { b: 2 } });
abs.getIn(['a', 'b']); // 2
// setIn:嵌套赋值
let foo = Immutable.fromJS({ a: { b: 1 } });
let bar = foo.setIn(['a', 'b'], 2);
console.log(foo.getIn(['a', 'b'])); // 1
console.log(foo === bar); // false
对比原生 JS:
let foo = { a: { b: 1 } };
let bar = foo;
bar.a.b = 2;
console.log(foo.a.b); // 2
console.log(foo === bar); // true
在 React 中应用
性能优化
在 shouldComponentUpdate 中使用 is 方法进行对比,避免深度比较:
import { is } from 'immutable';
shouldComponentUpdate(nextProps, nextState) {
return !is(this.props.data, nextProps.data);
}
组件状态管理
使用 Immutable 前需要深拷贝:
import _ from 'lodash';
handleAdd() {
let data = _.cloneDeep(this.state.data);
data.times = data.times + 1;
this.setState({ data: data });
}
使用 Immutable 后:
getInitialState() {
return {
data: Map({ times: 0 })
};
}
handleAdd() {
this.setState({
data: this.state.data.update('times', v => v + 1)
});
console.log(this.state.data.get('times')); // 不会改变
}
结合 Redux
import { fromJS } from 'immutable';
const defaultState = fromJS({
home: true,
focused: false
});
function reducer(state = defaultState, action) {
switch (action.type) {
case 'UPDATE_FOCUSED':
return state.set('focused', action.value);
default:
return state;
}
}
关键点
- Immutable 通过结构共享实现高性能的不可变数据,修改时只复制变化的节点
- 使用
is方法进行对象比较,避免深度比较带来的性能损耗 - 在 React 中可优化
shouldComponentUpdate,减少不必要的渲染 - 结合 Redux 使用时,用
fromJS转换初始状态,用set、update等方法更新数据 - 主要 API:
fromJS、toJS、is、get、getIn、set、setIn、update
目录