immutable 和redux-immutable
我们在状态管理时,是不允许直接修改state对象的,像之前这种代码
import { ADD_ITEM, CHANGE_INPUT, DELETE_ITEM } from './actionTypes'
const defaultState = {
inputValue: '123',
list: []
}
export default (state = defaultState, action) => {
if (action.type === CHANGE_INPUT) {
const newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState
}
if (action.type === ADD_ITEM) {
const newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
if (action.type === DELETE_ITEM) {
const newState = JSON.parse(JSON.stringify(state))
newState.list.splice(action.index, 1)
return newState
}
return state
}
这种原生js的形式因为state是无法直接更改的,因此往往需要对对象做深层拷贝并返回新对象的形式,有时候会增加性能损耗,这时候可以使用immutable来使数据不可被更改
当时用immutable.js 时, 使用 {formJS} ,使 JS对象 转化为 immutable对象,更改数据时,使用 get 与 set 方法 获取 和 设置 值
import * as actionTypes from './actionTypes'
import {fromJS} from 'immutable'
const defaultState =fromJS({
focused: false
})
const headerReducer = (state = defaultState, action) => {
if(action.type === actionTypes.FOCUS_INPUT) {
return state.set('focused', true);
}
if(action.type === actionTypes.BLUR_INPUT) {
return state.set('focused', false);
}
return state;
}
export default headerReducer;
此时由于原本的redux合并的combineReducers只支持原生可改变的state值,所以还需要借助redux-immutable来从state取出一个immutable 对象,如下
// import {combineReducers} from 'redux'; 从这里取 state 是一个js对象
import {combineReducers} from 'redux-immutable';// 从这里取 state 是一个immutable对象
import { reducer as headerReducer } from '../components/Header/store'
import { reducer as homeReducer } from '../pages/home/store'
import { reducer as detailReducer } from '../pages/detail/store'
import { reducer as loginReducer } from '../pages/login/store'
// 类似于vuex的module合并,会将这部分的内容封装至不同的参数下单独管理即header:{header单独的state状态管理}
export default combineReducers({
header: headerReducer,
home: homeReducer,
detail: detailReducer,
login: loginReducer
})
由于使用了新的redux-immutable来从reducer中取得了一个immutable对象,所以在组件中也不能用原生js点操作符来取数据了,所以
const mapStateToProps = (state) => {
return {
// focused: state.header.focused // 全是js 对象的时候这么调用
// focused: state.header.get('focused') //state是一个js 对象 的时候(只用immutable时)这么调用
// focused: state.get('header').get('focused') //state 和 focused 是immutable对象
focused: state.getIn(['header', 'focused']) //state 和 focused 是immutable对象
}
}
const mapDispatchToProps = (dispatch) => {
return {
handleInputFocus() {
dispatch(actionCreators.focusInput())
},
handleInputBlur() {
dispatch(actionCreators.blurInput())
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);
immutable.js使用过程中的一些注意点
- fromJS和toJS会深度转换数据,随之带来的开销较大,尽可能避免使用,单层数据转换使用Map()和List()
- js是弱类型,但Map类型的key必须是string!(也就是我们取值是要用get('1')而不是get(1))
- 所有针对immutable变量的增删改必须左边有赋值,因为所有操作都不会改变原来的值,只是生成一个新的变量
- 获取深层深套对象的值时不需要做每一层级的判空(JS中如果不判空会报错,immutable中只会给undefined)
- immutable对象直接可以转JSON.stringify(),不需要显式手动调用toJS()转原生
- 判断对象是否是空可以直接用size
- 调试过程中要看一个immutable变量中真实的值,可以chrome中加断点,在console中使用.toJS()方法来查看
immutable常用API
//Map() 原生object转Map对象 (只会转换第一层,注意和fromJS区别)
immutable.Map({name:'danny', age:18})
//List() 原生array转List对象 (只会转换第一层,注意和fromJS区别)
immutable.List([1,2,3,4,5])
//fromJS() 原生js转immutable对象 (深度转换,会将内部嵌套的对象和数组全部转成immutable)
immutable.fromJS([1,2,3,4,5]) //将原生array --> List
immutable.fromJS({name:'danny', age:18}) //将原生object --> Map
//toJS() immutable对象转原生js (深度转换,会将内部嵌套的Map和List全部转换成原生js)
immutableData.toJS();
//查看List或者map大小
immutableData.size 或者 immutableData.count()
// is() 判断两个immutable对象是否相等
immutable.is(imA, imB);
//merge() 对象合并
var imA = immutable.fromJS({a:1,b:2});
var imA = immutable.fromJS({c:3});
var imC = imA.merge(imB);
console.log(imC.toJS()) //{a:1,b:2,c:3}
//增删改查(所有操作都会返回新的值,不会修改原来值)
var immutableData = immutable.fromJS({
a:1,
b:2,
c:{
d:3
}
});
var data1 = immutableData.get('a') // data1 = 1
var data2 = immutableData.getIn(['c', 'd']) // data2 = 3 getIn用于深层结构访问
var data3 = immutableData.set('a' , 2); // data3中的 a = 2
var data4 = immutableData.setIn(['c', 'd'], 4); //data4中的 d = 4
var data5 = immutableData.update('a',function(x){return x+4}) //data5中的 a = 5
var data6 = immutableData.updateIn(['c', 'd'],function(x){return x+4}) //data6中的 d = 7
var data7 = immutableData.delete('a') //data7中的 a 不存在
var data8 = immutableData.deleteIn(['c', 'd']) //data8中的 d 不存在
相关连接
最近在学习react开发,整理几篇笔记方便自己查询使用,下面是连接地址
1.React 之 react-transition-group
2.React之 redux、react-redux、redux-thunk