immutable.js笔记

本文详细介绍了Immutable.js的原理,包括PersistentDataStructure和StructuralSharing,并通过实例展示了如何在React中使用Map和List进行不可变数据操作。此外,还演示了在Redux中如何利用Immutable.js进行状态管理,包括使用Map和fromJS方法创建不可变state,并通过set和setIn方法修改数据。最后,文章给出了一个完整的Redux应用示例,展示在App.js和Son.js组件中如何与store交互并更新状态。

Immutable.js原理分析

Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。

Immutable.js的使用

安装

cnpm i immutable --save

Map的操作

import React from 'react';
import ReactDOM from 'react-dom';
import {Map} from 'immutable';

//声明一个对象,这个对象要设置为不可被修改的对象
const state = {
  value: 'hello',
  list: ['html','css','js']
}

//将要设置不可更改的对象,传入到Map()方法中,会返回一个新的state对象
const imState = Map(state)

//将state对象设置为不可被修改的对象后,使用 get('key') 方法取值
console.log(imState.get('value'))

//使用set()方法修改值,修改后会返回一个新的对象,原来的对象数据没有变化
const newImState = imState.set('value','world')

console.log(imState.get('value'))
console.log(newImState.get('value'))


ReactDOM.render(
  <div>
    hello
  </div>
  ,document.getElementById('root'));

List的操作

import React from 'react';
import ReactDOM from 'react-dom';
import {List} from 'immutable';

//声明一个数据,要将该数组设置为不可更改的数组
const arry = [1,2,3]

//将数组传入 List() 中即可设置不可更改的数组对象
const imList = List(arry)

//对imList做追加操作,不会对原数组做修改,会返回一个新的数组对象
const newImList = imList.push(4)

console.log(imList.size,newImList.size)


ReactDOM.render(
  <div>
    hello
  </div>
  ,document.getElementById('root'));

fromJS的操作

import React from 'react';
import ReactDOM from 'react-dom';
import {fromJS} from 'immutable';

//声明一个不可更改的对象
const state = {
  value: 'hello',
  list: ['html','css','js'],
  obj: {
    x: 1,
    y: {
      z: 2
    }
  }
}

//把state传入的fromJS()中
const imState = fromJS(state)

//获取imState中的值
console.log(imState.get('value'))

//修改imState中的值,修改对象中的第一层属性的值,可以使用 set() 方法
const newState = imState.set('value','world')
console.log(newState.get('value'))

//修改imState中更深层次的数据,需要使用 setIn() 或 updateIn() 方法
//setIn() 可以直接赋值,参数1为对象属性的层级结构,按照层级顺序编写到数组中;参数2为要赋的值
const newState1 = imState.setIn(['obj','y','z'],100)
//updateIn() 可以对原始值做修改后再返回新的值,参数1同上,参数2为修改值时用的回调函数,回调函数的参数为对象原始值
const newState2 = imState.updateIn(['obj','y','z'], val => val + 1)

//获取深层对象结构的值,使用 getIn() 方法
console.log(newState1.getIn(['obj','y','z']))
console.log(newState2.getIn(['obj','y','z']))


ReactDOM.render(
  <div>
    hello
  </div>
  ,document.getElementById('root'));

在redux中使用immutable

使用Map操作

第1步:创建store

import {createStore} from 'redux'
import reducer from './reducer'

const store = createStore(reducer)

export default store

第2步:创建reducer

import {Map} from 'immutable'

//使用Map()来创建原始对象,创建的原始对象为不可更改的对象
const defaultState = Map({
    value: ''
})

const reducer = (state = defaultState, action)=>{

    //在执行修改state的代码中,使用 set() 方法完成修改操作,返回一个新的对象
    if(action.type === 'change_value'){
        return state.set('value',action.value)
    }

    return state
}

export default reducer

第3步:创建App.js文件,用于修改redux中的数据

import React, { Component } from 'react'
import store from './store'
import Son from './Son'

export default class App extends Component {

    constructor() {
        super()
        this.state = store.getState()
        store.subscribe(()=>{
            this.setState(store.getState())
        })
    }

	//文本框输入事件
    handleInput(e){
        let action = {
            type: 'change_value',
            value: e.target.value
        }
        store.dispatch(action)
    }

    render() {
        return (
            <div>
                <input value={this.state.value} onChange={this.handleInput.bind(this)}></input>
                <Son></Son>
            </div>
        )
    }
}

第4步:创建Son.js用于实时显示redux中的数据

import React, { Component } from 'react'
import store from './store'

export default class Son extends Component {

    constructor(){
        super()

        //此时使用store.getState()获取的数据为immutable处理后的对象,要使用get()方法获取具体值
        this.state = {
            value:  store.getState().get('value')
        }

        store.subscribe(()=>{
            this.setState({
                value: store.getState().get('value')
            })
        })
    }

    render() {
        return (
            <div>
                Son组件:{this.state.value}
            </div>
        )
    }
}

使用fromJS操作

App.js代码

import React, { Component } from 'react'
import store from './store'
import Son from './Son'

export default class App extends Component {


    constructor() {
        super()

        this.state = {
            value: '',
            name: '',
            age: 0,
            h1: ''
        }
    }

    //提交事件
    handleSubmit(){
        let action = {
            type: 'reg_user',
            value: this.state.value,
            name: this.state.name,
            age: this.state.age,
            h1: this.state.h1
        }
        store.dispatch(action)
    }


    render() {

        return (
            <div>
                <div>
                    普通值:<input value={this.state.value} onChange={(e)=>{
                        this.setState({value: e.target.value})
                    }}></input>
                </div>

                <div>
                    姓名:<input value={this.state.name} onChange={(e)=>{
                        this.setState({
                            name: e.target.value
                        })
                    }}></input>
                </div>

                <div>
                    年龄:<input value={this.state.age} onChange={(e)=>{
                        this.setState({
                            age: e.target.value
                        })
                    }}></input>
                </div>

                <div>
                    爱好:<input value={this.state.h1} onChange={(e)=>{
                        this.setState({
                            h1: e.target.value
                        })
                    }}></input>
                </div>

                <button onClick={this.handleSubmit.bind(this)}>提交</button>
                
                
                <hr />
                
                <Son></Son>
            </div>
        )
    }
}

store.js代码

import {createStore} from 'redux'
import reducer from './reducer'

const store = createStore(reducer)

export default store

reducer.js代码

import {fromJS} from 'immutable'

//使用Map()来创建原始对象,创建的原始对象为不可更改的对象
const defaultState = fromJS({
    value: '',
    user: {
        name: '',
        age: 0,
        hobby: {
            h1: ''
        }
    }
})

const reducer = (state = defaultState, action)=>{

    //使用fromJS中的 setIn() 方法修改数据
    if(action.type === 'reg_user'){

        return  state.setIn(['user','name'],action.name)
      .setIn(['user','age'],action.age)
      .setIn(['user','hobby','h1'],action.h1)
      .set('value',action.value)
    }

    return state
}

export default reducer

Son.js代码

import React, { Component } from 'react'
import store from './store'

export default class Son extends Component {

    constructor(){
        super()

        //此时store.getState()获取到数据为复杂类型,要使用getIn()方法
        const storeState = store.getState();
        this.state = {
            value:  storeState.get('value'),
            user: {
                name: storeState.getIn(['user','name']),
                age: storeState.getIn(['user','age']),
                hobby: {
                    h1: storeState.getIn(['user','hobby','h1'])
                }
            }
        }

        //监听store中的数据更新
        store.subscribe(()=>{
            const storeState2 = store.getState();
            this.setState({
                value:  storeState2.get('value'),
                user: {
                    name: storeState2.getIn(['user','name']),
                    age: storeState2.getIn(['user','age']),
                    hobby: {
                        h1: storeState2.getIn(['user','hobby','h1'])
                    }
                }
            })
        })
    }

    render() {
        let {value,user} = this.state
        return (
            <div>
                Son组件:{value}
                <p>姓名:{user.name}</p>
                <p>年龄:{user.age}</p>
                <p>爱好:{user.hobby.h1}</p>
            </div>
        )
    }
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涔溪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值