immutable是什么,优缺点以及如何在redux中使用

immutable的出现是为了性能优化,将可共享的数据提出,只更新改变的数据。减少性能消耗

immutable是什么?

官网:
https://immutable-js.github.io/immutable-js/
https://cloud.tencent.com/developer/section/1489374

  • JavaScript 中的对象一般是可变的(Mutable),因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象将影响到原始对象。如 foo={a: 1}; bar=foo; bar.a=2 你会发现此时 foo.a 也被改成了 2。虽然这样做可以节约内存,但当应用复杂后,这就造成了非常大的隐患,Mutable 带来的优点变得得不偿失。为了解决这个问题,一般的做法是使用 shallowCopy(浅拷贝)或 deepCopy(深拷贝)来避免被修改,但这样做造成了 CPU 和内存的浪费。

什么是不可变数据

  • Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
  • 持久化数据结构:这里说的持久化是用来描述一种数据结构,指一个数据,在被修改时,仍然能够保持修改前的状态,即不可变类型。
    结构共享:Immutable使用先进的tries(字典树)技术实现结构共享来解决性能问题,当我们对一个Immutable对象进行操作的时候,ImmutableJS会只clone该节点以及它的祖先节点,其他保持不变,这样可以共享相同的部分,大大提高性能。
    惰性操作:创建的对象时其实代码块没有被执行,只是被声明了,代码在获取或修改的时候才会实际被执行

在这里插入图片描述

immutable.js的优缺点

优点:

  • 降低mutable带来的复杂度
  • 节省内存
  • 并发安全
  • 历史追溯性(时间旅行):时间旅行指的是,每时每刻的值都被保留了,想回退到哪一步只要简单的将数据取出就行,想一下如果现在页面有个撤销的操作,撤销前的数据被保留了,只需要取出就行,这个特性在redux或者flux中特别有用
  • 拥抱函数式编程:immutable本来就是函数式编程的概念,纯函数式编程的特点就是,只要输入一致,输出必然一致,相比于面向对象,这样开发组件和调试更方便。推荐一本函数式编程的在线免费书《JS 函数式编程指南》。

缺点:

  • 需要重新学习api
  • 资源包大小增加(源码5000行左右)
  • 容易与原生对象混淆:由于api与原生不同,混用的话容易出错。

Immutable 的几种数据类型

  • List: 有序索引集,类似JavaScript中的Array。
  • Map: 无序索引集,类似JavaScript中的Object。
  • OrderedMap: 有序的Map,根据数据的set()进行排序。
  • Set: 没有重复值的集合。
  • OrderedSet: 有序的Set,根据数据的add进行排序。
  • Stack: 有序集合,支持使用unshift()和shift()添加和删除。
  • Range(): 返回一个Seq.Indexed类型的集合,这个方法有三个参数,start表示开始值,默认值为0,end表示结束值,默认为无穷大,step代表每次增大的数值,默认为1.如果start = end,则返回空集合。
  • Repeat(): 返回一个vSeq.Indexe类型的集合,这个方法有两个参数,value代表需要重复的值,times代表要重复的次数,默认为无穷大。
  • Record: 一个用于生成Record实例的类。类似于JavaScript的Object,但是只接收特定字符串为key,具有默认值。
  • Seq: 序列,但是可能不能由具体的数据结构支持。
  • Collection: 是构建所有数据结构的基类,不可以直接构建。

用的最多就是List和Map,所以在这里主要介绍这两种数据类型的API。

git地址: 以及使用方法 API的使用

Immutable 的常用API

安装 npm i -S immutable

  • Map(): 原生object转Map对象
const map1 = Map({ a: 1, b: 2, c: 3})
const map2 = Map({ a: 1, b: 2, c: 3})
console.log(map1 === map2) // false
console.log(map1.equals(map2)) // true
map.toJS() // 把map转为js对象
  • List(): 原生array转List对象
const list1 = List([1, 2]);
const list2 = list1.push(3, 4, 5);
// 获取值
console.log(list2.get(0));
const list1 = List([ 1, 2, 3 ]);
const list2 = List([ 4, 5, 6 ]);
const list3 = list2.concat(list1);
console.log(list3.toArray())
  • fromJS(): 原生js转immutable对象
const imState = fromJS({
  name: 'lisi',
  users: ['aa', 'bb']
})
  • 获取数据
imState.get('name')
console.log(imState.get('users').get(1))
console.log(imState.getIn(['users', 0]))
  • toJS(): immutable对象转原生js 不推荐使用
const state = imState.toJS()
console.log(state);
--------------------------------------------------------
  • set/setIn/update/updateIn 修改数据
const newState = imState.set('name', 'zhangsan')
const newState = imState.setIn(['name'], 'zhangsan')
const newState = imState.update('count', value => value + 1)
const newState = imState.updateIn(['count'], value => value + 1)

redux中集成immutable.js

  • 安装redux-immutable(npm i -S redux-immutable)
    redux中利用combineReducers来合并reducer并初始化state,redux自带的combineReducers只支持state是原生js形式的,所以需要使用redux-immutable提供的combineReducers来替换原来的方法。
  • 它的合并是支持immutable对象合并
import { combineReducers } from 'redux-immutable'
   		...
export default createStore(
 reducer,
 composeEnhancers(applyMiddleware(thunk))
)

把所有的reducer数据转换为immutable对象

import {fromJS} from 'immutable'
const defaultState = fromJS({})

在组件中使用react-redux取数据时,要时刻注意它是一个immutable对象

import React, { Component } from 'react';
import { connect } from 'react-redux'


@connect(state => {
  // return state.toJS()
  // console.log(state);
  return {
    username: state.getIn(['user', 'username']),
    users: state.getIn(['user', 'users'])
  }
}, null)
class App extends Component {
  render() {
    // console.log(this.props.users);
    return (
      <div>
        App--- {this.props.username}
        <hr />
        {
          this.props.users.map(item => (
            <li>{item.get('name')}</li>
          ))
        }
      </div>
    );
  }
}

export default App;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaxLoongLvs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值