在react/redux中使用Immutable
在redux中使用Immutable
1、什么是Immutable?
Immutable是一旦创建,就不能被更改的数据。
对Immutable对象的任何修改或添加删除操作都会返回一个新的Immutable对象。
Immutable实现的原理是:Persistent Data Structure(持久化数据结构),
也就是数据改变时(增删改)要保证旧数据同时可用且不变
为了避免深拷贝把所有节点都复制一遍带来的性能损耗,Immutable使用了Structural Sharing(结构共享)
即如果对象树节点发生变化,只修改这个结点和受它影响的父节点,其他节点共享
2、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 不存在
3、immutable可以让代码更简洁、提高性能、让redux更快更方便更安全
在redux中每个reducer都返回一个新的对象(数组),常常会看到这样的代码:
// reducer
...
return [
...oldArr.slice(0,3),
newValue,
...oldArr.slice(4)
];
为了返回新的对象(数组),不得不有上面奇怪的样子,
而在使用更深的数据结构时会变的更棘手。
让我们看看Immutable的做法:
// reducer
...
return oldArr.set(4, newValue);
Immutable使用了Structure Sharing会尽量复用内存,
甚至以前使用的对象也可以再次被复用,
未引用的对象会被垃圾回收。
4、immutable使用过程中的一些注意点
a、fromJS和toJS会深度转换数据,随之带来的开销较大,尽可能避免使用,单层数据转换使用Map()和List() b、js是弱类型,但Map类型的key必须是string!(也就是我们取值是要用get('1')而不是get(1)) c、所有针对immutable变量的增删改必须左边有赋值,因为所有操作都不会改变原来的值,只是生成一个新的变量 d、获取深层深套对象的值时不需要做每一层级的判空(JS中如果不判空会报错,immutable中只会给undefined) e、immutable对象直接可以转JSON.stringify(),不需要显式手动调用toJS()转原生 f、判断对象是否是空可以直接用size g、调试过程中要看一个immutable变量中真实的值,可以chrome中加断点,在console中使用.toJS()方法来查看
5、在react中使用immutable
react做性能优化时,可以使用shouldComponentUpdate(),
因为无论子组件用没用到父组件的参数只要父组件重新渲染了,
子组件就会重新渲染
而shouldComponentUpdate()很好地帮我们解决了这个问题,
//在render函数调用前判断:如果前后state中Number不变,通过return false阻止render调用
shouldComponentUpdate(nextProps,nextState){
if(nextState.Number == this.state.Number){
return false
}
}
通过这个钩子我们可以很巧妙地避免了很多组件的重新渲染这种浪费性能的行为。
但是这个钩子默认返回true,也就是说它默认是都重新渲染的,
那么就需要多次使用,
而我们在使用原生属性的时候,为了得出是true还是false
不得不使用deepCopy、deepCompare,
而这两种方法非常消耗性能
而在有了Immutable之后,
Immutable 则提供了简洁高效的判断数据是否变化的方法,
来减少 React 重复渲染,提高性能,只需 ===
和 is
比较就能知道是否需要执行 render()
,
而这个操作几乎 0 成本,所以可以极大提高性能。
修改后的 shouldComponentUpdate
是这样的:
import { is } from 'immutable'; shouldComponentUpdate: (nextProps = {}, nextState = {}) => {
const thisProps = this.props || {}, thisState = this.state || {}; //判断长度是否改变,长度改变的话,数据一定改一定需要重新渲染
if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
Object.keys(thisState).length !== Object.keys(nextState).length) {
return true;
} //当原数据和next的数据长度一致时需要遍历循环比较
for (const key in nextProps) {
if (!is(thisProps[key], nextProps[key])) {
return true;
}
} for (const key in nextState) {
if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
return true;
}
}
return false;
}
6、redux中应用immutable的小demo
a、我的demo大概是这样
b、store文件夹下的index.js中引入immutable
import { createStore, applyMiddleware } from 'redux' //引入immutable
import Immutable from 'immutable' import thunk from 'redux-thunk'
import reducers from './reducers' //变为map函数
const initialState = Immutable.Map(); //注入
const store = createStore(reducers, initialState, applyMiddleware(thunk)) export default store
c、store文件夹下的reducers.js中修改联合reducer的方法
//以前引入的是redux的combineReducers方法
// import { combineReducers } from 'redux' //现在改为引入redux-immutable中
import { combineReducers } from 'redux-immutable' import { reducer as cookbook } from 'pages/cookbook'
import { reducer as menu } from 'pages/menu' export default combineReducers({
cookbook,
menu
})
d、在actionType.js和actionCreator.js中无变化,仍是定义变量和获取数据
e、在页面的reducer.js中
import { CHANGE_FROM } from './actionTypes' //引入fromJS
import { fromJS } from 'immutable' //把获取到的数据变成immutable的Map()形式
const defaultState = fromJS({
from: 'category'
}) //对state进行改变的时候采用immutable的方法
export default (state=defaultState, action) => {
if (action.type === CHANGE_FROM) {
return state.set('from', action.from)
} return state
}
f、在页面使用的时候转化成原生使用
//通过toJS()方法转换为原生再进行map遍历
let data = this.props.categories && this.props.categories.get('热门').toJS().slice(0, 11).map((value, index) => {
return {
icon: value.img,
text: value.title
}
})
以上。
在react/redux中使用Immutable的更多相关文章
- Immutable.js 以及在 react+redux 项目中的实践
来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...
- 清晰理解redux中的
首先需要明白 Redux 的单一状态树的概念,所谓的单一状态树,就是指“所有的 state 都以一个对象树的形式储存在一个单一的 store 中.” 比如我们有这么一个状态树(或者你叫它状态对象也行) ...
- immutable.js 在React、Redux中的实践以及常用API简介
immutable.js 在React.Redux中的实践以及常用API简介 学习下 这个immutable Data 是什么鬼,有什么优点,好处等等 mark : https://yq.aliyu ...
- 在 react 项目里如何配合immutable在redux中使用
一.reducer文件的处理 先安装 immutable 与 redux-immutable yarn add immutable redux-immutable 我们可能会在很多地方定义子树,这就需 ...
- react脚手架改造(react/react-router/redux/eslint/karam/immutable/es6/webpack/Redux DevTools)
公司突然组织需要重新搭建一个基于node的论坛系统,前端采用react,上网找了一些脚手架,或多或少不能满足自己的需求,最终在基于YeoMan的react脚手架generator-react-webp ...
- 在 React Native 中使用 Redux 架构
前言 Redux 架构是 Flux 架构的一个变形,相对于 Flux,Redux 的复杂性相对较低,而且最为巧妙的是 React 应用可以看成由一个根组件连接着许多大大小小的组件的应用,Redux 也 ...
- 在react项目中使用redux-thunk,react-redux,redux;使用总结
先看是什么,再看怎么用: redux-thunk是一个redux的中间件,用来处理redux中的复杂逻辑,比如异步请求: redux-thunk中间件可以让action创建函数先不返回一个action ...
- 如何在非 React 项目中使用 Redux
本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...
- 如何优雅地在React项目中使用Redux
前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...
随机推荐
- 【UML】NO.71.EBook.9.UML.4.002-【PowerDesigner 16 从入门到精通】- RQM
1.0.0 Summary Tittle:[UML]NO.71.EBook.9.UML.4.002-[PowerDesigner 16 从入门到精通]- RQM Style:DesignPatter ...
- HBuilder/Mui开发ios使用上拉刷新导致滚动条无法使用的解决方法
HBuilder/Mui开发的APP使用上拉刷新,当滚动到底部是会触发上拉刷新,加载更多数据.但是ios上确是一个坑,导致滚动条无法滚动. 解决方法 放弃Mui的上拉刷新,自己使用JS实现. var ...
- Go 初体验 - channel.2 - 超时机制
channel 虽然很好用,但是我们也要考虑异常情况,比如:超时 go 语言怎么解决这个超时问题呢? 可以利用 select 语句: select 的用法与 switch 语言非常类似,由 selec ...
- Go 初体验 - 死锁的几种情况
go 语言里,channel 是一个重要的对象和概念,它是通信的基础实现 如何实例化: ch := make(chan int) 由 channel 通信引起的死锁共有3种: 第一种是因为给 ch 推 ...
- java poi 合并 word文档
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import jav ...
- ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 题目9 : Minimum
时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 You are given a list of integers a0, a1, …, a2^k-1. You need t ...
- jquery简易tab切换
切换tab 使用eq()函数 eq() 方法将匹配元素集缩减值指定 index 上的一个. //为项目 3 设置红色背景 <ul> <li>list item 1</li ...
- keepalived + nginx 搭建负载均衡集群
第一章 keepalived 1.1 keepalived 服务说明 Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现 ...
- 安装GDB-ImageWatch ,在QT中查看图像
GDB_ImageWatch是在Linux下基于QT编写图像处理程序的调试程序. 由于并非像ImageWatch一样由官方提供,而是在github上以代码的方式进行提供,我们在使用的时候需要自己编译, ...
- Python3 tkinter基础 Menu add_cascade 多级菜单 add_separator 分割线
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...