redux 工作原理及简版的底层实现

99 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

1.通常我们会如下引入

import { createStore } from 'redux'

简单设想其内部实际就是实现一个闭包,内部创建一个state,subscribtion,对外暴露getState,subscribe,dispatch,等方法操作内部state和subscribtion;

到出一个applyMiddleware 应用中间件,接收若干中间件参数,

目的加强dispatch,在dispatch调用reducer之前,依次调用每一个中间件,中间件是一个函数,初始化时会被执行两次,最后返回一个终极函数,大概这样,可以比作是洋葱级别的闭包,洋葱最内层的调用dispatch是调用外一层中间件,一层一层直到,最后我们最初的dispatch方法

function dispatch (action) {

state=reducer(state,action)

 subscribtion .forEach(v=>v())

return action

   }

两次执行中间件第一次,将顺序搞反,第二次又搞回来,所以最后执行顺序是爱情最初的样子。

const fun=({getStore,dispatch})=>(dispach)=>(actino){    

return dispatch(action);

}

export function createStore(reducer,enhancer){

//如果有中间件,就要在dispach执行reducer之前搞一些事情,

但是createStore,依然要创建,在原理基础上增强dispatch

将createStore和reducer交给enhancer处理

     if(enhancer){
从这里创建store

    return    enhancer(createStore)(reducer);

    }

      //内部变量

        let state;

      //内部变量存储订阅事件

        const subscribtion=[];

     //dispach方法,

//1调用reducer,将当前state和action将reduce返回值赋值给内部变量

//2调用所有的订阅事件

//返回action不重要,可以返回任何东西

        function dispatch (action) {

            state=reducer(state,action)

            subscribtion.forEach(v=>v())

            return action

        }
function subscribe(fn){
subscribtion .push(fn)
}
return {
store,
dispatch,
subscribe
}

}

//applyMiddleware在传入时先调用了一次,这一次是返回一个可以调用两次的函数,因//为//createStore里面我们这么搞的,applyMiddleware返回值又调用两次

// enhancer(createStore)(reducer);

export applyMiddleware(...fn){
reudcer可能是多个所以...解构一下子

    return createStore=>...arg=>{
此时创建store
let store=createStore(...arg)
获取dispatch
let  dispatch=store.dispatch
let api={
getState:store.getState,
dispatch:(...arg)=>disapch(...arg)
}
调用一下所有中间件给他们传入getState和dispatch参数,得到一个加强版的中间件数组
compile函数结果调用一下,从右往左调用一圈,顺序正常了
let chian=fn.map(item=>item(api))
合并所有的的中间件,加强版dispatch诞生,
dispatch=compile(chian)(dispatch)
}
变成洋葱模型函数里面调用函数每一层都闭包一个dispatch

但是并未执行从左到右一层套一层,

funtion compile(...fn){
return fn.reduce((left,rigth)=>(arg)=>rigth(left(arg)))

}

}

简单的reduce

默认值为首次初始化的值

function countReducer(store=1,action){  

  switch(action.type){     

   case "add":return store+1

        case "sub":return store-1 

       default :return store    }}

export default countReducer;

使用store

如果使用中间件要安装中间件

npm i redux-logger redux-thunk -S

import {createStore} from './store'

import reducer from './reducer'

import logger from 'redux-logger'

import thunk from 'redux-thunk'

const store=createStore(reducer,applyMiddleware(logger,thunk))