在 React 开发中 React 强调开发者无时无刻去关注 数据的纯度 无论是类组件中的 state 还是 redux 中的 state
JavaScript 中的对象一般是可变的(Mutable),因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象将影响到原始对象。如 foo={a: 1}; bar=foo; bar.a=2
此时 foo.a
也被改成了 2
。虽然这样做可以节约内存,但当应用复杂后,这就造成了非常大的隐患,Mutable 带来的优点变得得不偿失。为了解决这个问题,一般的做法是使用 shallowCopy(浅拷贝)或 deepCopy(深拷贝)来避免被修改,但这样做造成了 CPU 和内存的浪费。
上述问题等同于在A组件中修改公共状态 在B组件中同样也被修改了
遇到这种问题如何解决呢?
ES6中 (...)扩展运算符 & Object.assign ES5中 Object.freeze()
但是这种浅层拷贝有什么问题呢? 答:一般没有 除非对象过于庞大 才会带来性能问题以及内存浪费
可不可以做的更好?
可以! 使用 ImmutableJS 进行性能优化
Immutable 优点
-
Immutable 降低了 Mutable 带来的复杂度
-
节省内存
Immutable.js 使用了 Structure Sharing 会尽量复用内存,甚至以前使用的对象也可以再次被复用。没有被引用的对象会被垃圾回收。
- 拥抱函数式编程
Immutable 本身就是函数式编程中的概念,纯函数式编程比面向对象更适用于前端开发。因为只要输入一致,输出必然一致,这样开发的组件更易于调试和组装。
Immutable 本意为不可改变的 这个库弥补了 Javascript 没有不可变数据结构的问题 那他是如何做到不可变的呢?
ImmutableJS核心概念就一个 只要修改了对象,就会返回一个新的对象,旧的对象不会发生改变;且新的对象会尽可能利用原来对象的结构 即结构共享
同时利用了数据结构中的16叉树最大程度保证了树的深度问题 减少更新的结构
ImmutableJS 基本使用
ImutableJS常见API
ImutableJS数据结构
- Map:键值对集合,对应于 Object,ES6 也有专门的 Map 对象
- List:有序可重复的列表,对应于 Array
- Set:无序且不可重复的列表
JavaScript和ImmutableJS直接的转换
-
对象转换成Immutable对象:Map
-
数组转换成Immutable数组:List
-
深层转换:fromJS
-
Immutable类型转换js:toJS()
ImmutableJS的基本操作
-
修改数据:set
-
获取数据:get
const im = Immutable;
const info = {
name: 'xiaoming',
age: 28,
friends: {
name: 'xiaohong',
age: 32
}
}
// 对上方对象进行转化时
const infoIm = im.Map(info)
const obj = infoIm;
// 修改时需要用set进行修改 同时这里不会主动改这里对infoIm 而是生成一个新的对象
const infoIm2 = infoIm.set("name", '小明')
console.log(infoIm2);
// 通过get来取数据
console.log(obj.get('name'));
console.log(infoIm2.get('name'));
// list
const num = ['1', '2', '3', '4'];
const numIm = im.List(num)
console.log(numIm);
const arr = numIm.set(0, 11)
console.log(numIm.get(0));
console.log(arr.get(0));
console.log(infoIm.get('friends')); // {name: "xiaohong", age: 32} 普通对象
// 传入js对象或数组 转化为 Immutable类型
const infoIm3 = im.fromJS(info)
console.log(infoIm3.get('friends'));
ImutableJS 结合 Redux使用
yarn add immutable
由于Redux有且仅有一个store 但是可以拆分为多个reducer 我用一个其中一个reducer进行举例
修改前的Reducer
import { CONSTANTS } from "./constants";
// 创建默认状态
const defaultState = Map{
topBanners: [],
};
const reducer = (state = defaultState, action) => {
switch (action.type) {
case CONSTANTS:
return {...state, action.data}
default:
return state;
}};
export default reducer;
结合ImutableJS后的Reducer
import { Map } from "immutable";
import { CONSTANTS } from "./constants";
// 将 defaultState 转换成 Map类型
const defaultState = Map({
topBanners: [],
});
const reducer = (state = defaultState, action) => {
switch (action.type) {
case CONSTANTS:
// 调用Map对象中的set方法
return state.set("data", action.data);
default:
return state;
}};
export default reducer;
在主reducer进行合并
这里要说明一点: immutablejs里面的Map进行包裹 而 Redux 中的 combineReducers 源码里面实现过程是通过Object.key方式将每个模块的小reduer进行传递 如果这时候拿Map进行包裹肯定不是Map想要的数据结构
yarn add redux-immutable
import { combineReducers } from "redux-immutable";
import { reducer as recommend } from"@v/xxx/components/xxxxx/store/index";
const mergeReducer = combineReducers({
recommend,
});
export default mergeReducer;
总结
Immutable 可以给应用带来极大的性能提升,但是由于侵入性较强 是否使用必须考虑项目复杂程度
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!