最近在用 React-Dnd 做拖拽效果的时候,顺带学习到了 immutability-helper
这个库。我觉得它主要是让我们能够更加优雅的去操作并创建一个新对象。
用法
在不用到 immutability-helper
的情况下我们通常是这么操作对象和数组的:
myData.x.y.z = 7;
// or...
myData.a.b.push(9);
const newData = deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
const newData = Object.assign({}, myData, {
x: Object.assign({}, myData.x, {
y: Object.assign({}, myData.x.y, {z: 7}),
}),
a: Object.assign({}, myData.a, {b: myData.a.b.concat(9)})
});
在使用了 immutability-helper
后,操作对象变得优雅了起来。
import update from 'immutability-helper';
const newData = update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}
});
const initialArray = [1, 2, 3];
const newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
const collection = [1, 2, {a: [12, 17, 15]}];
const newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]
const obj = {a: 5, b: 3};
const newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
// => {a: 5, b: 6}
// This is equivalent, but gets verbose for deeply nested collections:
const newObj2 = update(obj, {b: {$set: obj.b * 2}});
下面是它的一些 API:
-
{$push: array}
===> Array.push() -
{$unshift: array}
===> Array.unshift() -
{$splice: array of arrays}
===> Array.splice -
{$set: any}
===> obj.a = 1,给对象某个元素赋值 -
{$toggle: array of strings}
toggles a list of boolean fields from the target object. -
{$unset: array of strings}
remove the list of keys in array from the target object. -
{$merge: object}
合并对象 - `{$apply: function} 通过函数将一个值转为另外一个值。
-
{$add: array of objects}
为 Map 或者 Set 添加一个值 -
{$remove: array of strings}
从 Map 或者 Set 移除一个值
我的场景
我有这么一个对象:
const data = [
{
id: 1,
name: '已解散',
tasks: [
{
id: 1,
text: 'Write a cool JS library'
},
{
id: 2,
text: 'Make it generic enough'
},
{
id: 3,
text: 'Write README'
}
]
},
{
id: 2,
name: '已删库',
tasks: [
{
id: 4,
text: 'Create some examples'
},
{
id: 5,
text: 'Spam in Twitter and IRC to promote it (note that this element is taller than the others)'
}
]
},
{
id: 3,
name: '已跑路',
tasks: [
{
id: 6,
text: '???'
},
{
id: 7,
text: 'ABC'
},
{
id: 8,
text: 'DDD'
},
{
id: 9,
text: 'AAA'
}
]
},
{
id: 4,
name: '已开源',
tasks: [
{
id: 10,
text: 'SSS'
},
{
id: 11,
text: 'VVV'
}
]
}
]
我需要将 data[i].tasks 里面的值重新排序或者移动(可以想象成看板的样子)。
下面是更新方式:
let TempData = update(data, {
[fromColumnIndex]: {
issues: issues =>
update(issues, {
$splice: [[fromIssueIndex, 1]]
})
}
})
TempData = update(TempData, {
[toColumnIndex]: {
issues: issues =>
update(issues, {
$splice: [[toIssueIndex, 0, TempIssue]]
})
}
})
setData(TempData)
可以看到,setData() 里面用了多次 update 函数来操作 data 中的 tasks 数组。并且 update 的第二个对象中可以有多个属性来同时操作对象的不同属性的变化。
最后
immutability-helper
在处理复杂对象的时候的确要比用原生 API 修改,然后深拷贝一个新的对象优雅很多。