保持数据Immutable的几种写法
# 0.前言
本篇博客的主题是数据的 Immutable
(不可变)特性。
在 React
中,官方鼓励开发者在开发的过程中,始终维持这数据的 Immutable
特性,在官网入门案例"井字棋"的编写中有过专门的说明。
ps.
immutable
特性只是官方所鼓励的,React
将所有的选择权都交给开发者,可以选择遵守,也可以不遵守。如果不遵守遇到的问题,例如使用shouldComponentUpdate
钩子函数时无法正确的区分new
|old
数据,从而无法对重复渲染问题进行优化。
对此,在 redux
中更是专门封装了 reducer
函数去规范化数据的创建流程,要求每次都需要返回一个新的状态:
// reducer 的本质就是 createNewState
const newState = createNewState(state,{"ACTION_TYPE", payload})
const createNewstate = (state,action)=> {
return newState
}
2
3
4
5
在之前的项目的编写过程中,我通常采用的是先对object
进行深|浅拷贝,修改后返回的方案,确实也比较简单有效,但是最近在阅读redux
中文网时,罗列了很多其他写法(主要就是...
扩展运算符写法),特此记录。
# 1.object的Immutable
a.当只有1层时,可以直接浅层拷贝
let newState = {...state}
b.当存在多层时,如需修改state.first.second[someId].fourth
,可以使用...
扩展运算符
function updateVeryNestedField(state, action) {
return {
....state,
first : {
...state.first,
second : {
...state.first.second,
[action.someId] : {
...state.first.second[action.someId],
fourth : action.someValue
}
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
c.最简单的是使用:JSON.stringfy
+JSON.parse
(只能支持7种数据子类型)
# 2.数组的Immutable
a. 插入|删除:使用 ...
扩展运算符拼接
function insertItem(array, action) {
return [
...array.slice(0, action.index),
action.item,
...array.slice(action.index)
]
}
function removeItem(array, action) {
return [
...array.slice(0, action.index),
...array.slice(action.index + 1)
];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
b.浅拷贝后,修改
function insertItem(array, action) {
let newArray = array.slice();
newArray.splice(action.index, 0, action.item);
return newArray;
}
function removeItem(array, action) {
let newArray = array.slice();
newArray.splice(action.index, 1);
return newArray;
}
2
3
4
5
6
7
8
9
10
11
c.使用filter
,弹出index
与当前的index
如果筛选出!==
的项,即delete
;如果===
,即filter
function removeItem(array, action) {
return array.filter( (item, index) => index !== action.index);
}
2
3
d. 更新数组中的一项,也可以使用map
在 map
中默认直接return item
,所以当遍历的index
和目标index
不相等时,直接弹出。
function updateObjectInArray(array, action) {
return array.map( (item, index) => {
if(index !== action.index) {
// 这不是我们关心的项-保持原来的值
return item;
}
// 否则, 这是我们关心的-返回一个更新的值
return {
...item,
...action.item
};
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.使用第三方Immutable库
目前,只使用过最火的 Immutable.js
库,不过 redux
只支持普通 JavaScript
对象,如果想要使用,需要结合 redux-immutable
库。
更多的 Immutable
库可以见:https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md (opens new window)
# 4.总结
以上只是罗列了一小部分写法,实际项目中还可以使用 loadash
,或者对单层数组还可以进行 slice
或者concat
等操作。总的来说,维持 data
不可变特性的方法还有很多,可以灵活使用。