美文网首页redux学习深入浅出React和Redux
【项目经验分享】离线缓存redux数据

【项目经验分享】离线缓存redux数据

作者: lazyTai | 来源:发表于2018-12-27 13:52 被阅读11次

    javascript的优点就是可以做任何事情,javascript的缺点就是有人试图用javascript做任何事情

    前言

    个人觉得redux就是一个大的全局的state,至于我们不能痛快的使用setState()这样的方法修改这个state就很烦,于是我自己结合项目的经验,写了2个方法,可以setStore和getStore,这样就能做到和使用state一样方便

    优点也是作用:

    每一次的setStore都会把数据放到localStorage和redux这2个地方
    getStore的时候,先从redux中拿,如果redux没有,就去localStorage中拿
    也就起到了缓存,离线redux数据的效果

    用到技术点

    • dva的model管理reducer和action
    • localStorage

    第一步,写dva的model

    //favorites
    
    import {getState, setState, setStateReducer} from "../util/uitls";
    import {effects} from 'dva/saga'
    
    const INIT_STATE = {
        //初始化的state
    }
    const Map = require('lodash.map')
    const namespace = 'favorites'
    const MODEL = {
        namespace,
        state: INIT_STATE,
        reducers: {
            setState: setStateReducer
        },
        effects: {
    //特点的修改state的方法,叫~snapShot~
            * snapShot({payload}, {call, put}) {
                var state = yield  getState(namespace)
                yield setState({
                    ...state,
                    ...payload
                })(namespace)
            },
    
        },
        subscriptions: {
            setup({dispatch, history}) {
            },
        },
    };
    
    export default MODEL
    
    
    //辅助方法 utils
    export function* getState(namespace) {
        var result = yield effects.select(state => state[namespace]);
        return Object.assign({}, result)
    }
    
    export function setState(obj, isStrict = false) {
        return (name_space) => {
            return effects.put({
                type: `${name_space}/setState`,
                payload: obj,
                isStrict
            })
        }
    }
    
    export function setStateReducer(state, actions) {
        var {payload} = actions
        return {...state, ...payload}
    }
    
    

    第二步 pageRedux

    原因:因为每个界面都要把redux的state注入到props里面,也就是写connect这东西,每个界面都需要的重复代码,封装一下咯

    //pageRedux.js
    import React from 'react';
    import {connect} from 'react-redux';
    import {setStoreUtil, getStoreUtil, initStoreFromLocal} from '../util/store'
    
    export default function (WrappedComponent) {
        class MyComponent extends React.Component {
            constructor(props) {
                super()
                initStoreFromLocal.call(props)
                this.getStore = getStoreUtil.bind(props)
                this.setStore = setStoreUtil.bind(props)
            }
    
            componentWillMount() {
                var self = this
            }
    
            render() {
                return (<WrappedComponent {...this.props} getStore={this.getStore} setStore={this.setStore}/>)
            }
        }
    
        return connect(function (state, myProps) {
            return {_store: state, store: state, ...myProps}
        }, function (dispatch, ownProps) {
            return {
                dispatch,
            }
        })(MyComponent)
    }
    

    initStoreFromLocal,getStoreUtil和setStoreUtil

    作用:每一次的setStore都会把数据放到localStorage和redux中
    getStore的时候,从redux中拿,如果redux没有,就去localStorage中拿
    也就起到了缓存,离线redux数据的效果

    import {getLocal, setLocal} from "./local";
    
    export function setStoreUtil(namespace_key, value) {
        var props = this;
        var namespace = namespace_key.split('.')[0]
        var key = namespace_key.split('.')[1]
        setLocal(`${namespace}.${key}`, value)
        return props.dispatch({
            type: `${namespace}/snapShot`, payload: {[key]: value}
        })
    }
    
    export function getStoreUtil(namespace_key) {
        var namespace = namespace_key.split('.')[0]
        var key = namespace_key.split('.')[1]
        var props = this;
        var value = undefined;
        if (props.store[`${namespace}`]) {
            value = props.store[`${namespace}`][key]
            if (value instanceof Array) {
                if (value.length == 0) {
                    return getLocal(`${namespace}.${key}`) || []
                }
            }
            if (typeof(value) == "number") {
                if (value == 0) {
                    return 0
                } else {
                    return value || getLocal(`${namespace}.${key}`)
                }
            }
    
        }
    
        return value || getLocal(`${namespace}.${key}`)
    }
    
    //initStoreFromLocal的作用是在界面初始化的时候,把localStorage的数据,放到redux中
    export function initStoreFromLocal() {
        var props = this;
        var l = localStorage.length
        for (var i = 0; i < l; i++) {
            var key = localStorage.key(i)
            var _isTrue = key.split(".").length == 2
            if (_isTrue) {
                var namespace = key.split('.')[0]
                var key = key.split('.')[1]
                props.dispatch({
                    type: `${namespace}/snapShot`, payload: {[key]: getLocal(`${namespace}.${key}`)}
                })
            }
        }
    }
    
    //帮助操作缓存工具  local.js
    export const setLocal = function (key, value) {
        var storage = window.localStorage;
        if (value) {
            storage.setItem(key, JSON.stringify(value));
        } else {
            console.error("value undefined", value)
        }
    
    }
    export const clearLocal = function (key) {
        var storage = window.localStorage;
        storage.removeItem(key);
    }
    export const getLocal = function (key) {
        var storage = window.localStorage;
        return JSON.parse(storage.getItem(key));
    }
    

    使用

    终于再完成了前面的设置之后,我们可以在界面上很开心方便的操作数据啦

    this.props.setStore("app.lists",{...})
    var lists=this.props.getStore("app.lists")
    

    效果

    这是在redux中的数据


    image.png

    在localStorage的数据


    image.png

    END

    相关文章

      网友评论

        本文标题:【项目经验分享】离线缓存redux数据

        本文链接:https://www.haomeiwen.com/subject/lxyrlqtx.html