持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
一、Immutable(不可变数据)概念
Immutable Data不可更改数据,一旦创建,对Immutable对象的任何操作都将返回一个新的Immutable Data,其实现原理是
Persistent Data Structure(持久化数据结构) 即使用旧数据创建新数据时,要保证旧数据可以使用且不变。同时为了避免deepclone,深度拷贝对于性能的损耗,Immutable 使用了Structural Sharing(结构共享),当对象树中一个节点发生变化时,只会改变该子节点以及受其影响的父节点,其他节点共享。
Immutable data encourages pure functions (data-in, data-out) and lends itself to much simpler application development and enabling techniques from functional programming such as lazy evaluation. github.com/immutable-j…
二、基础使用
1.安装
npm i immutable
2.普通对象转为immutable对象
import {Map} from 'immutable'
var obj={
name:"test"
}
const oldData=Map(obj)
3.设置新的immutable对象
const newData=oldData.set('name','changename')
// set方法可以链式使用
const newData=oldData.set('name','changename').set('age',100)
打印新旧immutable对象会发现生成一个新的immutable对象,并且旧数据未改变。
4.获取immutable对象值
(1)get获取
const data=oldData.get('name')
(2)immutable转为普通对象
注意:toJs为深度拷贝比较耗费性能
const datanew=oldData.toJS()
5.组件state中使用
- 方式一
在数据初始化即state中将数据转为immutable不可变数据。在获取及修改数据时都要使用immutable的API。
import React, { Component } from 'react'
import {Map} from 'immutable'
export default class member extends Component {
state={
userInfo:Map({name:'test',age:100})
}
render() {
return (
<div>
<p>{this.state.userInfo.get('name')}</p>
<p>{this.state.userInfo.get('age')}</p>
<button onClick={()=>{
this.setState({
userInfo:this.state.userInfo.set('name','changename').set('age',99)
})
}}>set修改</button>
</div>
)
}
}
- 方式二
在数据修改时先将state中将数据获取转为immutable不可变数据。修改数据时要使用immutable的API。然后再将数据转为普通对象后设置回state,state中的数据始终是普通对象。
import React, { Component } from 'react'
import {Map} from 'immutable'
export default class member extends Component {
state={
userInfo:{name:'test',age:100}
}
render() {
return (
<div>
<p>{this.state.userInfo.name}</p>
<p>{this.state.userInfo.age}</p>
<button onClick={()=>{
const olddata=Map(this.state.userInfo)
const newdata=olddata.set('name','changename').set('age',99)
this.setState({
userInfo:newdata.toJS()
})
}}>set修改</button>
</div>
)
}
}
6.复杂类型使用
如果是多级数据结构,在子级前再包裹一层map,否则子级为普通对象.
state={
userInfo:Map({
name:'test',
age:100,
children:Map({
name:'one'
})
})
}
7.数组使用
数组使用List,并且被转化后的数组可以遍历,也可以使用数组相应的方法.
const arr=List([1,2,3])
arr.push(4)
const data=arr.toJs()
三、进阶使用
1.复杂类型使用fromJs
在基础使用中,我们给每个子级添加Map方法包裹,但实际情况中,后端返回的数据我们并不能准确地知道数据结构,因此使用fromJs直接将其转为immutable对象。注意该方法为深度拷贝,较为耗费性能。
import {fromJS} from 'immutable'
state={
userInfo:fromJS({
name:'test',
age:100,
children:{
name:'one'
}
})
}
2.setIn方法
可以使用层级方法设置数据,第一个参数为数组,按层级依次传入属性名,第二个参数为要设置的属性值
import React, { Component } from 'react'
import {fromJS} from 'immutable'
export default class member extends Component {
state={
userInfo:fromJS({
name:'test',
age:100,
children:{
name:'one'
}
})
}
render() {
return (
<div>
<p>{this.state.userInfo.get('children').get('name')}</p>
<button onClick={()=>{
this.setState({
userInfo:this.state.userInfo.setIn(['children','name'],'changeone')
})
}}>setIn修改</button>
</div>
)
}
}
3.updateIn
数组更新方法,第一个参数为数组,同setIn一样,为层级属性名,第二个为回调函数,updataIn方法会将immutable数组更新为回调函数中返回的数组
import React, { Component } from 'react'
import {fromJS} from 'immutable'
export default class member extends Component {
state={
userInfo:fromJS({
arr:[1,2,3,4]
})
}
render() {
return (
<div>
<button onClick={()=>{
this.setState({
userInfo:this.state.userInfo.update(['arr'],()=>[5,6,7,8])
},()=>{
console.log(this.state.userInfo)
})
}}>updateIn修改</button>
</div>
)
}
}