简介
每次修改一个 Immutable 对象时都会创建一个新的不可变的对象,在新对象上操作并不会影响到原对象的数据。
作用
- 深拷贝:react修改数据时,不想让原数据发生改变,所有使用拷贝再赋值的方式。但
const obj1 = JSON.parse(JSON.stringify(obj)); 的缺点: 不能有undefined,否则会遗失(没有完全实现深拷贝) - 优化新能: Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要 保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用 了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点, 其它节点则进行共享。
基本用法
Map & List -创建(单个)
- get:获取
set:设置
const { Map } = require('immutable');const map1 = Map({ a: 1, b: 2, c: 3 });const map2 = map1.set('b', 50);map1.get('b') + " vs. " + map2.get('b'); // 2 vs. 50
List可以使用数组方法
//assert.equal()函数是nodejs提供的断言函数,测试实际参数和预期参数之间的相等性。如果条件为真,则不会产生输出,否则会引发断言错误。const { List } = require('immutable');const list1 = List([ 1, 2 ]);const list2 = list1.push(3, 4, 5);const list3 = list2.unshift(0);const list4 = list1.concat(list2, list3);assert.equal(list1.size, 2);assert.equal(list2.size, 5);assert.equal(list3.size, 6);assert.equal(list4.size, 13);assert.equal(list4.get(0), 1);//push, set, unshift or splice 都可以直接用,返回一个新的immutable对象
merge & concat -合并
merge:合并对象
concat:合并数组
const { Map, List } = require('immutable');const map1 = Map({ a: 1, b: 2, c: 3, d: 4 });const map2 = Map({ c: 10, a: 20, t: 30 });const obj = { d: 100, o: 200, g: 300 };const map3 = map1.merge(map2, obj);// Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }const list1 = List([ 1, 2, 3 ]);const list2 = List([ 4, 5, 6 ]);const array = [ 7, 8, 9 ];const list3 = list1.concat(list2, array);// List [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
toJS -解析
toObject:将Map转换回来
- toArray:将List转换回来
toJS:将两者都转换
const { Map, List } = require('immutable');const deep = Map({ a: 1, b: 2, c: List([ 3, 4, 5 ]) });console.log(deep.toObject()); // { a: 1, b: 2, c: List [ 3, 4, 5 ] }console.log(deep.toArray()); // [ 1, 2, List [ 3, 4, 5 ] ]console.log(deep.toJS()); // { a: 1, b: 2, c: [ 3, 4, 5 ] }JSON.stringify(deep); // '{"a":1,"b":2,"c":[3,4,5]}'
fromJS -创建(多个)
fromJS:深层次添加Map和List
- getIn:获取(深)
- setIn:设置(深)
- updateIn:回调函数更新(深)
- mergeDeep:保留自身情况下并深克隆且转换为Map和List ```javascript const { fromJS } = require(‘immutable’); const nested = fromJS({ a: { b: { c: [ 3, 4, 5 ] } } }); // Map { a: Map { b: Map { c: List [ 3, 4, 5 ] } } }
const nested2 = nested.mergeDeep({ a: { b: { d: 6 } } }); // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }
console.log(nested2.getIn([ ‘a’, ‘b’, ‘d’ ])); // 6 //如果取一级属性 直接通过get方法,如果取多级属性 getIn([“a”,”b”,”c”]])
//setIn 设置新的值 const nested3 = nested2.setIn([ ‘a’, ‘b’, ‘d’ ], “kerwin”); // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: “kerwin” } } }
//updateIn 回调函数更新 const nested3 = nested2.updateIn([ ‘a’, ‘b’, ‘d’ ], value => value + 1); console.log(nested3); // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } } const nested4 = nested3.updateIn([ ‘a’, ‘b’, ‘c’ ], list => list.push(6)); // Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }
<a name="g3k9h"></a>
# Redux中使用
```javascript
//reducer.js
const initialState = fromJS({ //转换为Map和List
category:"",
material:""
})
const reducer = (prevstate = initialState,action={})=>{
let {type,payload} = action
switch(type){
case GET_HOME:
//set方法设置(不改变initialState)
var newstate =prevstate.set("category",fromJS(payload.category))
var newstate2 =newstate.set("material",fromJS(payload.material))
return newstate2;
default:
return prevstate
}
}
//home.js
const mapStateToProps = (state)=>{
return {
//getIn深层次获取state数据
category:state.homeReducer.getIn(["category"]) || Map({}),
material:state.homeReducer.getIn(["material"]) || Map({})
}
}
this.props.category.get("相关属性")
this.props.category.toJS() //或者转成普通对象
