redux v3.7.2源码解读与学习之 createStore(核心方法)

继上一篇:redux v3.7.2源码详细解读与学习之compose


redux是什么、有什么作用,解决什么问题,如果你还不知道,请先去这里: redux中文文档

下面的文章适合对redux有一定理解和使用经验的人

项目github地址:github.com/wangweiange…

如果你觉得对你有帮助的话记得给我一个star呢

createStore 是redux中最核心的代码,下面我们一步一步来实现一个简易版的 createStore。


1.新建一个simpleCreateStore.js 文件,创建一个createStore函数

var ActionTypes = {
  INIT: '@@redux/INIT'
}
function createStore(reducer, preloadedState, enhancer){}复制代码


2.createStore内部添加,getState、subscribe、dispatch、replaceReducer 4个空函数,并return出来

function createStore(reducer, preloadedState, enhancer){
    function getState(){}
    function subscribe(){}
    function dispatch(){}
    function replaceReducer(){}

    return {
        getState,
        subscribe,
        dispatch,
        replaceReducer
    }

}复制代码


3.我们来给点参数使函数运行起来,代码如下:

const ADD_TODO = 'ADD_TODO'
function todos(state = [], action) {
    switch (action.type) {
        case 'ADD_TODO':
            return state.concat([ action.text ])
        default:
            return state
    }
}
let store = createStore(todos,[ 'Use Redux' ])
console.log(store)复制代码

下面我们来一一的实现这个几个方法的内容。


4.实现getState方法

getState方法最简单直接返回函数内定义的currentReducer变量即可,代码如下:

function createStore(reducer, preloadedState, enhancer){
   let currentState = preloadedState

    function getState(){
        return currentState
    }

    function subscribe(){}
    function dispatch(){}
    function replaceReducer(){}

    return {
        getState,
        subscribe,
        dispatch,
        replaceReducer
    }

}复制代码

5.实现dispatch方法,此方法是redux的核心方法

var ActionTypes = {
  INIT: '@@redux/INIT'
}

function createStore(reducer, preloadedState, enhancer){
    let currentState = preloadedState
    let currentReducer = reducer

    function getState(){
        return currentState
    }
    function subscribe(){}
    function dispatch(action){
        currentState = currentReducer(currentState, action)
        return action
    }
    function replaceReducer(){}
    return {
        getState,
        subscribe,
        dispatch,
        replaceReducer
    }
}


const ADD_TODO = 'ADD_TODO'
function todos(state = [], action) {
    switch (action.type) {
        case 'ADD_TODO':
            return state.concat([ action.text ])
        default:
            return state
    }
}

let store = createStore(todos,[ 'Use Redux' ])
console.log(store.getState())复制代码

代码很简单,现在调用 store.getState() 试试吧,是不是得到了 ["Use Redux"] 这个值呢。

现在来调用一下dispatch这个方法吧,看看是不是能得到 ["Use Redux", "Read the docs"] 呢?

let actions = store.dispatch({
  type: 'ADD_TODO',
  text: 'Read the docs'
})复制代码


6.实现subscribe方法,并返回一个unsubscribe的方法,相应的dispatch运行监听变化:

function createStore(reducer, preloadedState, enhancer){
    let currentState = preloadedState
    let currentReducer = reducer
    let nextListeners = []

    function getState(){
        return currentState
    }
    function subscribe(listener){
        nextListeners.push(listener)
        return function unsubscribe() {
            const index = nextListeners.indexOf(listener)
            nextListeners.splice(index, 1)
        }
    }
    function dispatch(action){
        currentState = currentReducer(currentState, action)
        for (let i = 0; i < nextListeners.length; i++) {
            const listener = nextListeners[i]
            listener()
        }
        return action
    }
    function replaceReducer(){}

    return {
        getState,
        subscribe,
        dispatch,
        replaceReducer
    }
}复制代码

方法写好了我们来写个测试案例:

let currentValue
function handleChange() {
  let previousValue = currentValue
  currentValue = store.getState()
  if (previousValue !== currentValue) {
    console.log('store数据从', previousValue, '变为', currentValue)
  }
}

let unsubscribe = store.subscribe(handleChange)复制代码

掉一下dispatch方法看看日志记录吧。


7.实现replaceReducer方法,此方法也很简单

function createStore(reducer, preloadedState, enhancer){
    let currentState = preloadedState
    let currentReducer = reducer
    let nextListeners = []

    function getState(){
        return currentState
    }
    function subscribe(listener){
        nextListeners.push(listener)
        return function unsubscribe() {
            const index = nextListeners.indexOf(listener)
            nextListeners.splice(index, 1)
        }
    }
    function dispatch(action){
        currentState = currentReducer(currentState, action)
        for (let i = 0; i < nextListeners.length; i++) {
            const listener = nextListeners[i]
            listener()
        }
        return action
    }
    function replaceReducer(nextReducer) {
        currentReducer = nextReducer
        dispatch({ type: ActionTypes.INIT })
    }

    return {
        getState,
        subscribe,
        dispatch,
        replaceReducer
    }
}复制代码


9.最后运行createStore函数式初始化一次dispatch, dispatch({ type: ActionTypes.INIT })

最终代码如下:

var ActionTypes = {
  INIT: '@@redux/INIT'
}

function createStore(reducer, preloadedState, enhancer){
    let currentState = preloadedState
    let currentReducer = reducer
    let nextListeners = []

    function getState(){
        return currentState
    }
    function subscribe(listener){
        nextListeners.push(listener)
        return function unsubscribe() {
            const index = nextListeners.indexOf(listener)
            nextListeners.splice(index, 1)
        }
    }
    function dispatch(action){
        currentState = currentReducer(currentState, action)
        for (let i = 0; i < nextListeners.length; i++) {
            const listener = nextListeners[i]
            listener()
        }
        return action
    }
    function replaceReducer(nextReducer) {
        currentReducer = nextReducer
        dispatch({ type: ActionTypes.INIT })
    }
    dispatch({ type: ActionTypes.INIT })
    return {
        getState,
        subscribe,
        dispatch,
        replaceReducer
    }
}

//-------------------测试代码---------------------------

const ADD_TODO = 'ADD_TODO'
function todos(state = [], action) {
    switch (action.type) {
        case 'ADD_TODO':
            return state.concat([ action.text ])
        default:
            return state
    }
}

let store = createStore(todos,[ 'Use Redux' ])

let currentValue
function handleChange() {
  let previousValue = currentValue
  currentValue = store.getState()
  if (previousValue !== currentValue) {
    console.log('store数据从', previousValue, '变为', currentValue)
  }
}

let unsubscribe = store.subscribe(handleChange)

let actions = store.dispatch({
  type: 'ADD_TODO',
  text: 'Read the docs'
})

console.log(store.getState())复制代码


OK经过上面的一通敲打之后,其实你已经完成了一次redux createStore.js源码的构建,现在再去看看我github项目中对createStore.js的代码备注吧,相信你现在能很顺畅的自上而下的熟读。

贴一张图片:



接下来我们进入到redux的另一个工具方法 combineReducers

redux v3.7.2源码解读与学习之 combineReducers


关注我的博客:zane的个人博客

原文地址:redux v3.7.2源码解读与学习之 createStore


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值