在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的更多相关文章

  1. Immutable.js 以及在 react+redux 项目中的实践

    来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...

  2. 清晰理解redux中的

    首先需要明白 Redux 的单一状态树的概念,所谓的单一状态树,就是指“所有的 state 都以一个对象树的形式储存在一个单一的 store 中.” 比如我们有这么一个状态树(或者你叫它状态对象也行) ...

  3. immutable.js 在React、Redux中的实践以及常用API简介

    immutable.js 在React.Redux中的实践以及常用API简介 学习下 这个immutable Data 是什么鬼,有什么优点,好处等等 mark :  https://yq.aliyu ...

  4. 在 react 项目里如何配合immutable在redux中使用

    一.reducer文件的处理 先安装 immutable 与 redux-immutable yarn add immutable redux-immutable 我们可能会在很多地方定义子树,这就需 ...

  5. react脚手架改造(react/react-router/redux/eslint/karam/immutable/es6/webpack/Redux DevTools)

    公司突然组织需要重新搭建一个基于node的论坛系统,前端采用react,上网找了一些脚手架,或多或少不能满足自己的需求,最终在基于YeoMan的react脚手架generator-react-webp ...

  6. 在 React Native 中使用 Redux 架构

    前言 Redux 架构是 Flux 架构的一个变形,相对于 Flux,Redux 的复杂性相对较低,而且最为巧妙的是 React 应用可以看成由一个根组件连接着许多大大小小的组件的应用,Redux 也 ...

  7. 在react项目中使用redux-thunk,react-redux,redux;使用总结

    先看是什么,再看怎么用: redux-thunk是一个redux的中间件,用来处理redux中的复杂逻辑,比如异步请求: redux-thunk中间件可以让action创建函数先不返回一个action ...

  8. 如何在非 React 项目中使用 Redux

    本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...

  9. 如何优雅地在React项目中使用Redux

    前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...

随机推荐

  1. Android -- 从源码带你从EventBus2.0飚到EventBus3.0

    1,最近看了不少的面试题,不管是百度.网易.阿里的面试题,都会问到EventBus源码和RxJava源码,而自己只是在项目中使用过,却没有去用心的了解它底层是怎么实现的,所以今天就和大家一起来学习学习 ...

  2. 浅谈react的初步试用

    现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Face ...

  3. 关于angular2 打包(一)

    在讲到angular2 及以上项目打包之前,我先讲一下.angular cli 拥有自己的打包工具,熟悉的可以直接上手.如果用不惯,也可以去使用webpack 之类的.内置的systemjs也是很好用 ...

  4. Access restriction: The type 'Unsafe' is not API

    错误:Access restriction: The type 'Unsafe' is not API Eclipse中有一种叫做存取限制的机制,来防止你错误使用那些非共享的API.通常来说,Ecli ...

  5. 普通文件的上传(表单上传和ajax文件异步上传)

    一.表单上传: html客户端部分: <form action="upload.ashx" method="post" enctype="mul ...

  6. 清理Visual Studio 2017的项目历史记录或手工修改Visual Studio 2017的注册表设置

    Visual Studio 2017的"最近的文件列表"和"项目列表"总是删了之后重启电脑又出现(PS:这期间没有打开过项目,更没打开过VS). 一怒之下,按照 ...

  7. Appium+python自动化1-环境搭建(上)

    前言 appium可以说是做app最火的一个自动化框架,它的主要优势是支持android和ios,另外脚本语言也是支持java和Python.小编擅长Python,所以接下来的教程是appium+py ...

  8. Zeu.js

    一个生成各种 GIF 动画的 JavaScript 类库,非常适合用于让你的数据展示变得更加地生动.使用起来也非常简单,有数据展示需求的同学可以尝试一下.https://shzlw.github.io ...

  9. iOS项目之交换方法(runtime)

    在项目中,经常会遇到系统自带的方法满足不了自己的需求,往往我们解决这种情况的时候,都是在分类中添加一个方法.然而很多时候,项目已经开发很长时间了,如果一个一个的去替换系统的方法,太浪费宝贵的时间,所以 ...

  10. 4. Dubbo原理解析-代理之接口定义 (转)

    转载自  斩秋的专栏  http://blog.csdn.net/quhongwei_zhanqiu/article/details/41577159 一:ProxyFactory的接口定义 impo ...