mini-redux实现

130 阅读4分钟

思路

通过使用redux,我们可以发现createStore是用于创建仓库,组件调用store.dispatch(action)进行数据更新,然后再通过store.subcribe的回调函数更新组件

createStore函数的实现

首先我们通过使用createStore可以得到一个对象,里头包含subscribe, dispatch,getState三个方法:

getState返回的是当前的状态值,

dispatch是通过传入的action进行状态值的修改 subscribe则是更新完状态值要做的事情

由此我们可以得知函数大概样子

export const function createstore(reducer){
  let currentState ;
  let currentLisenters = []
  const getState   =  () => currentState
  const dispatch = (action) => {
    currentState = reducer(currentState,action) //其实就是调用一下reducer函数进行修改
    currentLisenters.forEach(lisenters => {//通知更新(执行回调函数)达到更新组件的目的
       lisenters()
    })
  }
  const subscribe = lisenters => {currentLisenters.push(lisenters)} //订阅更新
  return {
    getState,
    dispatch,
    subscribe
  }
}

由于初始化需要默认的状态值,所以我们需要首先执行一下dispatch,只需要简单的传个毫不关联的action就可以,让它执行默认的reducer的default逻辑

export const function createstore(reducer){
  let currentState ;
  let currentLisenters = []
  const getState   =  () => currentState
  const dispatch = (action) => {
    currentState = reducer(currentState,action) //其实就是调用一下reducer函数进行修改
    currentLisenters.forEach(lisenters => {//通知更新(执行回调函数)达到更新组件的目的
       lisenters()
    })
  }
  const subscribe = lisenters => {currentLisenters.push(lisenters)} //订阅更新
  dispatch({action.type:New Date()}) //初始化状态值并更新组件
  return {
    getState,
    dispatch,
    subscribe
  }
}

applyMiddleware函数实现

由于上面的函数不支持异步更新,由此就需要applyMiddleware来实现 我们可以思考下applyMiddleware的功能就是将函数聚合执行,并加强了dispatch

接下来我们开始改造下最初的createStore函数

export const function createstore(reducer,enhancer){
  let currentState ;
  let currentLisenters = []
  if(enhancer){//只有当enhancer存在的时候我们才需要增强我们的dispatch
    return enhancer(createStore)(reducer)
    
  }
  const getState   =  () => currentState
  const dispatch = (action) => {
    currentState = reducer(currentState,action) //其实就是调用一下reducer函数进行修改
    currentLisenters.forEach(lisenters => {//通知更新(执行回调函数)达到更新组件的目的
       lisenters()
    })
  }
  const subscribe = lisenters => {currentLisenters.push(lisenters)} //订阅更新
  return {
    getState,
    dispatch,
    subscribe
  }
}
export const applyMiddleware = (...middlewares) => (createStore) => (reducer) => {
   //传入createStore是由于我们在中间件的时候需要store的控制权,reducer则为我们需要的更新逻辑
   const store = createStore(reducer)
   const midApi = {getState:store.getState,dispatch:action => dispatch(action)}
   //我们需要将控制权传递给中间件,以此让他们可以控制状态仓库
   const chain = middlewares.map(middleware => middleware(midApi))

   return {
    ...store,
    dispatch
   }
}

//增强的dispatch就是将一个个中间件函数聚合起来,然后执行。在此之前我们需要一个函数帮我们把传入的中间件一个一个执行一下有此我们需要聚合函数

compose函数的实现

function compose(...funcs){聚合函数
  if(funcs.length === 0)return args =>  args //兼容性的提升 const a = compose(f1,f2), a(111)
  if(funcs.length === 1)return funcs[0]
  return funcs.reduce((prev,cur) => (...args) => prev(cur(...args)))
}

接下来我们重新填充上面的增强的dispatch实现

export const function createstore(reducer,enhancer){
  let currentState ;
  let currentLisenters = []
  if(enhancer){//只有当enhancer存在的时候我们才需要增强我们的dispatch
    return enhancer(createStore)(reducer)
    
  }
  const getState   =  () => currentState
  const dispatch = (action) => {
    currentState = reducer(currentState,action) //其实就是调用一下reducer函数进行修改
    currentLisenters.forEach(lisenters => {//通知更新(执行回调函数)达到更新组件的目的
       lisenters()
    })
  }
  const subscribe = lisenters => {currentLisenters.push(lisenters)} //订阅更新
  return {
    getState,
    dispatch,
    subscribe
  }
}
export const applyMiddleware = (...middlewares) => (createStore) => (reducer) => {
   //传入createStore是由于我们在中间件的时候需要store的控制权,reducer则为我们需要的更新逻辑
   const store = createStore(reducer)
   let dispatch = store.dispatch
   const midApi = {getState:store.getState,dispatch:action => dispatch(action)}
   //我们需要将控制权传递给中间件,以此让他们可以控制状态仓库
   const chain = middlewares.map(middleware => middleware(midApi))//将各个中间件执行传入控制权
   //增强dispatch 将原先的store.dispatch传入进去
   dispatch = compose(...chain)(store.dispatch)
   return {
    ...store,
    dispatch
   }
}
function compose(...funcs){//聚合函数
  if(funcs.length === 0)return args =>  args //兼容性的提升 const a = compose(f1,f2), a(111)
  if(funcs.length === 1)return funcs[0]
  return funcs.reduce((prev,cur) => (...args) => prev(cur(...args)))
}

redux中间件插件的实现

这里的next即为下一个函数,next(action)是把action传入下一个next进行调用

redux-logger的实现

function logger({getState,dispatch}){
  return (next) => (action) => {
     const prevState = getState()
     conosole.log('prevState',prevState)
     //next是compose下一个函数例如applyMiddleware(thunk,logger)
     //则logger传入的next则为dispatch
     //如applyMiddleware(logger,thunk)
     //则logger传入的next为thunk函数
     const returnValue = next(action)
     const curState = getState()
     return returnValue
  }
}

redux-thunk的实现

function thunk({getState,dispatch}){
  return next => action => {
    //判断action是否是函数如果是则说明是个异步调用
    if(typeof action === 'function'){
      //我们只需要直接调用该函数即可并且传入状态仓库的控制权
      return action(dispatch,getState)
    }
    return next(action)
  }
}

combineReducers的实现

combineReducers的用法为combineReducers({count:countReducer,num:numReducer}) 我们可以知道combineReducers就是将之前的单一的reducer变成一个新的reducer只不过这个新的reducer的state为整合起来的对象

export default combineReducers(reducers){
  //{num:numreducer}
 return function mergeReducer(state={},action){
   let nextState = {}//整合成一个state
   let hasOnchanged = false
   for(let key in reducers){//遍历reducers根据属性生成新的state
     const reducer = reducers[key] 
     nextState[key] = reducer(state[key],action)
     hasOnchanged = hasOnchanged || nextState[key] === state[key] //就是判断这两次的state是否一样
   }
   return hasOnchanged ? nextState : state
 }
}