实现redux核心API

180 阅读2分钟

学习过react的同学都知道redux这个状态管理库,或许同学们都对这个库的API用得溜得起飞,我刚开始学习的时候总觉得redux太难了,相对于vue的vuex来说,redux的学习成本相对较高,vuex已经有自己自带的模板,上手比较容易。但是当你了解过redux后,其实内部的几个常用的API实现起来其实并没有想象中那么难。

createStore

使用redux的基本操作都是创建一个存储状态store变量,它通过readux的createStore方法创建而来,我们尝试实现一个自己的createStore。

新建一个my-redux的文件夹,在文件下新建一个createStore.js的文件,在这里实现核心的createStore方法。

createStore方法接两个参数,reducer是一个纯函数,enhancer加强函数,用来处理中间件。

export default function createStore(reducer, enhancer) {    
    if (enhancer) {        
        return enhancer(createStore)(reducer)    
    }    
    let currentState    
    let currentListeners = []    
    function getState() {        
        return currentState    
    }    
    function dispatch(action) {        
        currentState = reducer(currentState, action)        
        currentListeners.forEach(listener => listener())    
    }    
    function subscribe(listener) {        
        currentListeners.push(listener)        
        return () => {            
                const index = currentListeners.indexOf(listener)            
                currentListeners.splice(index ,1)        
            }    
       }    
    dispatch({ type: 'REDUX/DREAM' })    
    return {        
        getState,        
        dispatch,        
        subscribe    
    }
}

createStore方法最终返回getState,dispatch,subscribe三个方法,getState用来获取store的当前状态,dispatch用来修改状态,subscribe用来处理当数据发生改变,需要做什么。

首先,先判断是否有enhancer方法,有的话先进行对createStore的进一步加强,传入reducer得到最终的结果。createStore方法的reducer是必传项,reducer是一个纯函数。通过action的类型来改变currentState的值,currentListners用于执行相应的队列。subscribe用于发布和取消订阅。在createStore方法里需要初始化自动派发dispatch。

applyMiddleware

redux除了createStore核心的API之外,还提供了applyMiddleware方法。顾名思义,这个方法用于处理中间件,配合createStore一起使用,applyMiddleware可以接收一系列的中间件。新建一个applyMiddleware.js文件来编写核心的applyMiddleware。

在函数执行的时候,要保证函数会按照顺序挨个执行,我们定义一个compose函数来辅助,需要判断空数组的兼容情况。

function compose(...funs) {    
    if (funs.length === 0) {        
        return arg => arg    
    }    
    if (funs.length === 1) {        
        return funs[0]    
    }    
    return funs.reduce((a, b) => (...args) => a(b(...args)))
} 

export default function applyMiddleware(...middlewares) {    
    return createStore => reducer => {        
        const store = createStore(reducer)        
        let dispatch = store.dispatch        
        const midApi = {            
            getState: store.getState,            
            dispatch: action => dispatch(action)        
        }        
        const middlewareChain = middlewares.map(middleware => middleware(midApi))        
        dispatch = compose(...middlewareChain)(store.dispatch)        
        return {            
            ...store,            
            dispatch        
        }    
    }
}

中间件的加强其主要针对的是dispatch的加强,在redux中,store.dispatch派发的action类型只能是对象,在applyMiddleware中,dispatch的加强通过compose方法来完成。最终将store和dispatch导出,dispatch会覆盖原本store的dispatch。

大体的实现就是这样了的啦,想深入学习的同学去github查看源码。