概述-----不可变数据

immutablejs库,它给我们创建了一新的js对象,此对象数据是不可变结构化数据。数据结构共享。 Immutable.js出自Facebook,是最流行的不可变数据结构的实现之一。它实现了完全的持久化数据结构,使用结构共享。所有的更新操作都会返回新的值,但是在内部结构是共享的,来减少内存占用。
  • 因为在redux中,通过reducer函数对state处理过程中是一个对象的深复制。
  • 采用immutable将会降低对象深复带来的复杂度

1.3、安装

  • npm i -S immutable

1.4、常用API

  • fromJs()------优点:会自动转换。
  • 将纯js对象和数组通过递归进行深层转为List和Map
  • 参数(json:any,reviver:()=>{})
  • 如果没有提供reviver,默认行为会将数组转换为列表和对象到地图中。
  • 将原始对象转换为Map
1 import { Map, List, fromJS } from 'immutable'
2 fromJS(): 原生js转immutable对象
3 const imState = fromJS({
4   name: 'lisi',
5   users: ['aa', 'bb']
6 })

 

List(): 原生array转List对象
它可以把js中的数组对象转为 immutable中的List方法只能转换一维数组,如果是多维的,则不推荐
 
Map:它可以把js中的json对象转为 immutable中的Map对象,Map方法只能转换json对象第1层,不会递归到后续层级中,用它转换的json对象如果层级较多,则推荐
 
获取数据
get/getIn
get /getIn
const obj = { id: 1, info: { name:   'lisi' , age: 20, arr: [1, 2] } }
// const state = fromJS(obj)
// console.log(state.get('name'))
// console.log(state.getIn(['name']))
// console.log(state.get('info').get('name')) 、、不推荐
// console.log(state.getIn(['info', 'name']))  可以获取info对象下name的值
// console.log(state.getIn(['info', 'arr', 1]))  获取info下arr的索引为1的值

把immutable对象转为普通的js对象   immutable对象.toJS()  =》 转为js对象

console.log(state.get('info').toJS())
// 把immutable对象转为普通的js对象   immutable对象.toJS()  =》 转为js对象
// console.log(state.get('info').toJS())
修改  set/setIn  update/updateIn
修改  set/setIn  update/updateIn
// set/setIn 对原数据进行覆盖
// update/updateIn 在原数据的基础上进行操作  update/updateIn可以实现set/setIn中的功能
// const obj = { id: 1, name: 'lisi', age: 20 }
// const state = fromJS(obj)
// const newState = state.set('name', '张三')
// const newState = state.setIn(['name'], '张三 IN')
// 在原数数据进行操作
// const newState = state.update('age', value => value + 1)
// const newState = state.updateIn(['age'], value => value + 10)

// 删除操作 delete/deleteIn/remove/removeIn  -- 了解就可以
// const newState = state.remove('name')

//  合并
// const state1 = fromJS({ id: 1, name: 'lisi'})
// const state2 = fromJS({ age: 20 })
// const newState = state1.merge(state2)
// console.log(newState.toJS())
// 合并方案
// console.log(fromJS({...state1.toJS(),...state2.toJS()}))

// // 对象比较  一般在react如果用,则是对于性能优化上所用
// const state1 = fromJS({ id: 1, name: 'lisi'})
// const state2 = fromJS({ id: 1, name: 'lisi'})

// // js比对,比对是地址,两个对象,地址肯定不同,所以返回false
// // console.log(state1 === state2)
// // immutable中它对于immutable对象提供一个方法 equals 比对immutable对象值是否相同,如果相同则返回true,反之false
// console.log(state1.equals(state2))

//------------------------- List
// const arr = [1, 2, 3, { id: 1, name: '李四' }]
// // List转换,只转换第1层,不递归
// // const state = List(arr)
// const state = fromJS(arr)

// 获取
// console.log(state.get(1))
// console.log(state.getIn([1]))
// console.log(state.getIn([3,'name']))
// 得到长度 属性
// console.log(state.size)

// 修改 pop/shift/push/unshift/concat/splice    /set/setIn/update/updateIn
// const newState = state.update(2,v => v+3)
// const newState = state.push(10)
// const newState = state.concat(fromJS([10,20]))

// const s1 = fromJS([1, 2])
// const s2 = fromJS([3, 4])
// const newState = fromJS([...s1, ...s2])
// console.log(newState.toJS())

// remove/removeIn
// const s1 = fromJS([1, 2])
// const newState = s1.remove(0)
// console.log(newState.toJS())

 

1.5 redux集成immutable

  1. 使用基本步骤
  2. 将store中的initState【同步的】,转为immutable对象。
  3. 在reducer中,返回一个新的immutable对象。使用immutable后,在reducer中处理数据无需进行深复制
  4. 采用update()将对应的数据进行修改。
  5. 组件当中依赖react-redux来获取store中的数据,但是获取的不是普通对象,需要用toJs()

😆组件中

 

import { connect } from 'react-redux'
@connect(
  state => state.get('count').toJS(),
  {
    add() {
      return { type: 'count_add', data: 10 }
    }
  }
)
class App extends Component {
  render() {
    return (
      <div>
        <h3>{this.props.num}</h3>
        <button onClick={this.props.add}>修改</button>
      </div>
    )
  }
}

 

redux中
 
import { createStore, applyMiddleware } from 'redux'
// 开启浏览器中的redux调试工具
import { composeWithDevTools } from '@redux-devtools/extension'
// 引入immutable库
import { fromJS } from 'immutable'

// 把普通json对象转为 immutable对象给redux
const initState = fromJS({
  count: 100
})

const reducer = (state = initState, { type, data = 1 }) => {
  if ('add' === type) {
    // immutable对象的操作,会返回一个新的immutable对象
    // 使用immutable后,在reducer中处理数据就无需进行深复制
    return state.update('count', v => v + data)
  }

  // 返回的是一个immutable对象,它不是一个普通的json对象
  return state
}

const store = createStore(reducer, composeWithDevTools())

export default store

1.6 多个reducer进行整合处理

 将每一个reducer进行划分出去,放置在reducer中;

在里面进行初始值的设置,并且返回一个新immutable并导出;
在store中有一个总reducer,是借助于immutable中的combineReducers进行整合

 

单个reducer
// 引入immutable库
import { fromJS } from 'immutable'

// 把普通json对象转为 immutable对象给redux
const initState = fromJS({
  films: []
})

const reducer = (state = initState, { type, data }) => {
  if ('film_add' === type) {
    // immutable对象的操作,会返回一个新的immutable对象
    // 使用immutable后,在reducer中处理数据就无需进行深复制
    return state.set('films', data)
  }

  // 返回的是一个immutable对象,它不是一个普通的json对象
  return state
}

export default reducer

 

 

总reducer
// import { createStore, applyMiddleware, combineReducers } from 'redux'
import { createStore, applyMiddleware } from 'redux'
// 开启浏览器中的redux调试工具
import { composeWithDevTools } from '@redux-devtools/extension'
import thunk from 'redux-thunk'
import { combineReducers } from 'redux-immutable'

import count from '../reducer/count'
import film from '../reducer/film'

// 如果用redux中的 combineReducers 方法合并多个小的reducer,它返回的是一个 js普通对象,所以redux中用到了immutable,则一般不用内置此方法,而是安装一个 redux-immutable 库,则库中提供一个方法combineReducers,它就可以把合并后的对象也转为immutable对象,操作起来就变得统一了
const reducer = combineReducers({
  count,
  film
})

const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk)))

export default store

1.7 immer的提出,优化setState操作

Immer是mobx的作者写的一个 immutable 库,核心实现是利用 ES6 的 Proxy,几乎以最小的成本实现了 js 的不可变数据结构,简单易用、体量小巧、设计巧妙,满足了我们对JS不可变数据结构的需求。

 

安装
npm i -S immer

主要实现将数据进行代理,可变化数据,但可共享结构;也就是说;一个数据对象中,代理此对象,更改对象中的数组,代理对象的数组和源对象数组不相等,但若未更改源对象中某一个对象的数据,该代理对象和源对象中的对象时相等的。即未发生结构变化。
 
此外,produce,返回一个新的state,
参数1:源数据,
参数2:回调函数中的形参为元数据的浅复制对象

 

// 引入immer类  不可变结构变化数据,共享数据结构
import { produce } from 'immer'



const currentState = {
  arr: [],
  obj: {
    id: 1
  }
}

const newState = produce(currentState, draft => {
  draft.arr.push(1)
})
console.log(newState.arr === currentState.arr)  // false
console.log(newState.obj === currentState.obj)  // true
 

 可以用来优化setState,也就是produce的写法二

  1. // 回调函数不能有返回值
  // produce只有一个参数,为回调函数,写在setState中,它把draft映射到this.state对象代理               // 因为现在draft它是一个代理对象,可以直接去操作,不用像之前哪样key:value               // 回调函数不能有返回值
import {produce} from  'immer'
class App extends Components{
    const initState={
    count:100
}


    
    render(){
        return(
            <div>
            <h3>{this.initState.count}</h3>
            <button
            onClick={()=>{
                
             // this.setState(state => ({ count: state.count + 1 }))
            // immer来优化setState写法
            
                this.setState(
                    prodece(draft=>{
                        draft.count++                    
                    })                
                )            
            }}
            >++</button>
            </div>        
        )    
    }
}

1.8 使用immer来优化reducer

 使用immerse来优化reducer,使用第一种写法,两个参数,第一个是初始数据,第二个是修改数据的回调函数

在store中
  • 一定记得produce需要一个初始值,跟reduce一样

 

import {produce} from 'immer'
const initState={
    count:100
}

const  reducer=prodece((draft,{type,data})=>{
    if(type==='count_add'){
        //之前在这的深复制,不需要
        draft.count+=data    
    }
},initState)
在组件调用中
import {connect} from 'react-redux'

@connect(state=>state,{
    add(){
        return {type:'count_add',data:10}    
    }
})

class App extends Components{
    render(){
        <div>
        <h3>{this.props.count}</h3>
        <button 
        onClick={this.props.add}
        ></button>
        </div>    
    }
}

 

 

 

 

posted on 2022-06-30 17:34  瞿~锐〃  阅读(53)  评论(0)    收藏  举报