【dva】dva使用与实现(四)

前言

  • 上一篇说的dynamic,这一篇实现onAction和onStateChage。

利用onAction实现redux-logger

  • 这个使用在第一篇就说过了,从第二篇loading的实现可以发现redux-logger使用的是onAction的钩子。而onAction其实是个中间件钩子。
  • 所以我们需要把自己写的dva里把钩子加入中间件。
  • 首先就是把前面写的钩子管理机里的hooks增加上onAction
const hooks = [
    "onEffect",//增强effect
    "extraReducers",//添加reducer
    "onAction"//增加中间件
]
  • 这样dva里面可以通过plugin.get获取到传来的onAction的中间件了。
  • 然后在中间件位置加入:
  let extraMiddleware = plugin.get('onAction')
  let store = applyMiddleware(routerMiddleware(history), sagaMiddleware, ...extraMiddleware)(createStore)(reducer)
  • 这样使用官方的logger就可以打印出日志了。
  • 下面实现logger,其实就是写个redux中间件。
const logger = ({ dispatch, getState }) => next => action => {
    let prevState = getState()
    next(action)
    let nextState = getState()
    console.log('prev state', prevState);
    console.log('action', action);
    console.log('next state', nextState);

}
export default logger
  • 中间件格式一模一样。调用next会给下一个中间件,走完里面的最后出来再拿值就是改调的state了,这也是洋葱模型。

  • 我们可以再修改一下,变得和logger打印出来样式一样。
    在这里插入图片描述

  • 我们把样式添加上:

const logger = ({ dispatch, getState }) => next => action => {
    let prevState = getState()
    next(action)
    let nextState = getState()

    console.group(
        `%caction %c${action.type} %c@${new Date().toLocaleTimeString()}`,
        `color:grey;font-weight:lighter`,
        `font-weight:bold`,
        'color:grey;font-weight:lighter'
    )
    console.log('%cprev state', `color:#9E9E9E; font-weight:bold`, prevState);
    console.log('%caction', `color:#03A9F4; font-weight:bold`, action);
    console.log('%cnext state', `color:#4CAF50; font-weight:bold`, nextState);
    console.groupEnd()
}
export default logger
  • 这样打印的东西就跟原版一模一样了。

利用onStateChage持久化

  • 这个是有插件的,第六篇说,先从最简单的实现开始讲,主要还是为了实现一个onStateChage的钩子。
  • 首先是使用,先全部用原版的:
app.use({
    onStateChange(state) {
        localStorage.setItem('state', JSON.stringify(state))
    }
})
  • 这个就是做的onStateChage钩子,每当状态发生变更就会执行这个回调函数。这个函数里面写的就是把state存进loacalstorage。读取等会再说,先实现存入。
  • onStateChange是个钩子,所以在plugin.js里加入这个钩子:
const hooks = [
    "onEffect",//增强effect
    "extraReducers",//添加reducer
    "onAction",
    "onStateChange"
]
  • 然后,这里就需要使用store.subscribe了。在redux这篇文章里可以发现store.subscribe就是传入listener,然后当dispatch时候会调用listener,所以这里在拿到store后,加入这么一句:
        let onStateChange = plugin.get('onStateChange')
        store.subscribe(() => {
            onStateChange.forEach(fn => fn(store.getState()))
        })
  • 这个函数就是当dispatch时会调用这个函数,让所有写在onStateChange上的函数全部执行。
  • 有人可能会觉得这个跟加中间件有点像,什么时候加中间件,什么时候用subscribe。中间件对拦截的dispatch做操作,理论上也可以完成subscribe的操作,但是得注意中间件的顺序。中间件可进行的操作大于subscribe。redux那文章中可以看见subscribe的方法在dispatch中执行,调用dispatch就是执行subscribe。而中间件是可以把dispatch进行改写或在dispatch外面操作,所以subscribe在dispatch外面调用和里面调用都是可以的。
  • 这样就完成了状态变更存入storage。有存也得有取,不然刷新就没了。
  • 这里就要利用store的初始值了:
let app = dva({
  initialState: localStorage.getItem('state') ? JSON.parse(localStorage.getItem('state')) : undefined
})
  • 还需要在dva的index.js中写入它:
  let store = applyMiddleware(routerMiddleware(history), sagaMiddleware, ...extraMiddleware)(createStore)(reducer, opts.initialState)
  • 这样便完成了。store本来第二个参数是初始值,直接传给它就行了。一开始初学的时候感觉store的初始值好像没啥用,现在发现这个初始值真是特别好用。
发布了163 篇原创文章 · 获赞 9 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/yehuozhili/article/details/104073852
dva