初探immutable Redux+immutable实现todolist

Posted ltfxy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初探immutable Redux+immutable实现todolist相关的知识,希望对你有一定的参考价值。

初探immutable Redux+immutable实现todolist

immutable的实现原理是Persistent Data Structrue 持久化数据解构

特点是结构共享带来的性能优化

持久化数据结构

所谓持久化数据结构,就是说,当数据改变时,不会改变原数据,而是返回一个经过改变的新数据。

你可以使用这个新数据,处理拷贝引用类型时属性之间存在引用关系的问题。当然深拷贝也可以处理这个问题,但显然immutable是更高效的方式。

这个特性适用于redux中的reducer

import {Map} from ‘immutable‘

let map = Map({a:1})
let map1 = map.set({b:2})

console.log(map) // 0: (2) ["a", 1]
console.log(map1) // 0: (2) ["a", 1] 1: Array(2) 0: {b: 2}

结构共享

对immutable来说,基于旧数据返回的新数据,如果新数据的某些节点没有变化,那么会继续沿用,从而到达了尽量复用内存的效果。相比于拷贝所有节点的深克隆来说,immutable在性能上是具有优势的

技术图片

优点

降低mutable带来的复杂度(引用类型你懂的)
节省内存(结构共享)
时间旅行
函数式编程

缺点

学习api
资源包大小增加
容易与原生对象混淆

使用immutable

Map 数据结构

import { Map } from ‘immutable‘
const map = Map({
    a:1,
    b:2,
    c:3
})
const obj = {
    a:1,
    b:2,
    c:3
}
//判断是否immutable原生Map
console.log(Map.isMap(map), Map.isMap(obj)) // true  false
// get/set 取/存值

List

import { List } from ‘immutable‘

//初始化
const list = List([1,2,3,4])
//添加
const newList = list.push(5)
//删除,返回新的list,[1,3,4]
const list1 = list.delete(1)

console.log(list,newList)

//不能通过下标取值,只能通过get取值
console.log(list[4],newList[4])
console.log(newList.get(4))//5
//判断类型
console.log(List.isList(newList))

//判断相等
const anotherList = List([1,2,3,4]);
console.log(list === anotherList) /// false 
console.log(list.equals(anotherList)) // true

类型比较

如果两个map键值对相同,那么用赋值判断是false
但是用isEquals判断是true

//判断相等
const anotherList = List([1,2,3,4]);
console.log(list == anotherList) /// false 
console.log(list === anotherList) /// false 
console.log(list.equals(anotherList)) // true

类型转换

import { Map,fromJS } from ‘immutable‘
const map = Map({
    a:1,
    b:2,
    c:3
})
const obj = {
    a:1,
    b:2,
    c:4
}

const merge = map.merge(map,obj); //合并,相同属性会覆盖
console.log(merge)

console.log(map.toJS())//转成js对象
console.log(map.toObject())//转成js对象
console.log(fromJS(obj))

深层拷贝

import { fromJS } from ‘immutable‘

const nest1 = fromJS({ a: { b: { c: [3, 4, 5] } } });

const nest2 = nest1.mergeDeep({a:{b:{d:6}}})

//获取值,浅层和深层
console.log(nest2.getIn([‘a‘,‘b‘,‘d‘]))//这里获取的是a.b.d

//更新值
const n3 = nest2.updateIn([‘a‘,‘b‘,‘d‘],value=>value+1);
console.log(n3.getIn([‘a‘,‘b‘,‘d‘]))//7

redux+immutable实现todolist

为了演示只实现CRUD中的增删,其他实现方式类似

除了react脚手架之外需要的install的插件

  • react-redux
  • immutable
  • redux

1 创建reducer,更新并返回state

使用immuta中的List作为数据结构,返回新state时对于不改变的节点能够保留,达到复用内存优化性能的效果

import { List } from ‘immutable‘

//初始state
const defaultState = new List([]);

const reducer = (state = defaultState, action) => {
    switch (action.type) {
        case ‘ADD‘:
            return state.push(
                {
                    id: Math.floor(Math.random() * 100),
                    data: action.data
                }
            )
        case ‘DEL‘:
            return state.filter(item => item.id !== action.data)
        default:
            return state;
    }
}

export default reducer;

2 创建store

import { createStore } from "redux";
import reducer from "./reducer";

const store = createStore(reducer)

export default store;

3 连接redux与React组件之一 connect.js

mapState为组件提供状态state,mapDispatch为组件提供方法

import {connect} from ‘react-redux‘

const mapState = (state)=>{
    return {
        list:state
    }
}

const mapDispatch = (dispatch)=>{
    return{
        add:(data)=>{
            dispatch({
                type:"ADD",
                data
            })
        },
        del:(data)=>{
            dispatch({
                type:"DEL",
                data
            })
        }
    }
}

export default connect(mapState,mapDispatch);

4 连接redux与React组件之二:入口js文件中Provider包裹todolist组件,提供store

import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import ‘./index.css‘;

import Todolist from ‘./20-immutable/todolist/Todolist‘
import { Provider } from ‘react-redux‘
import store from ‘./20-immutable/todolist/store/index‘

ReactDOM.render(
  <Provider store={store}>
    <Todolist></Todolist>,
   </Provider>,
  document.getElementById(‘root‘)
);

5 连接redux与React组件之三:高阶组件,connect增强导出

增强导出之后可以用this.props拿到redux store进行后续的渲染与抛发的操作

import React, { Component } from ‘react‘
import Form from ‘./Form‘;
import List from ‘./List‘;


import connect from ‘./store/connect‘;

class Todolist extends Component {

    render() {
        return (
            <div>
                <Form add={this.props.add}></Form>
                <List></List>
            </div>
        )
    }
}

export default connect(Todolist);

6 List.jsx

import React, { Component } from ‘react‘

import connect from ‘./store/connect‘;

class List extends Component {
    
    handleClick(id){
        this.props.del(id)
    }
    
    render() {
        return (
            <ul>
                {
                    this.props.list.map(item => {
                        return (
                            <div key={item.id}>
                                <li >{item.data}</li>
                                <button onClick={this.handleClick.bind(this,item.id)} >删除</button>
                            </div>
                        )
                    })
                }
            </ul>
        )
    }
}

export default connect(List);






以上是关于初探immutable Redux+immutable实现todolist的主要内容,如果未能解决你的问题,请参考以下文章

immutable在redux中的应用

在react/redux中使用Immutable

Redux 开发工具 Chrome 扩展 Immutable.js 导致错误

在对象中设置值时 Redux 数据不重新呈现(Immutable.js)

Redux & Immutable.js - 从 json 设置状态

在 react 项目里应用 immutable 对 redux 进行处理,对 List 数据渲染的问题