一文搞懂 Immutable.js-不可变数据

1,378 阅读3分钟

热点关注首图.jpg 持续创作,加速成长!这是我参与「掘金日新计划 · 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…

e2f6a31a3ee3416fadd2dd5f7584c507_tplv-k3u1fbpfcp-watermark.gif

二、基础使用

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对象,并且旧数据未改变。

捕获.PNG

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>
    )
  }
}