react-redux部分关键源码解析

硬菜源码解析(部分关键源码):

createStore

export default function createStore(reducer, initialState) {
// 这些都是闭包变量
var currentReducer = reducer
var currentState = initialState
var listeners = []
var isDispatching = false;

// 返回当前的state,核心方法之一
function getState() {
return currentState
}

// 注册listener,同时返回一个取消事件注册的方法,核心方法之二
function subscribe(listener) {
listeners.push(listener)
var isSubscribed = true

return function unsubscribe() {
//解绑是将 listeners 都移除掉,在后续 dispatch 中不存在 listeners
  if (!isSubscribed) {
     return
  }
  isSubscribed = false
  var index = listeners.indexOf(listener)
  listeners.splice(index, 1)
  }
}
// 通过action该改变state,然后执行subscribe注册的方法,核心方法之三
function dispatch(action) {
 try {
  isDispatching = true
  currentState = currentReducer(currentState, action)
} finally {
  isDispatching = false
}
//在发出 action 后触发 subscribe 的 listeners,执行该方法
listeners.slice().forEach(listener => listener())
return action
}

// 替换reducer,修改state变化的逻辑,核心方法之四
function replaceReducer(nextReducer) {
currentReducer = nextReducer
dispatch({ type: ActionTypes.INIT })
}
// 创建store时,执行内部一个dispatch,得到初始state
dispatch({ type: ActionTypes.INIT })
}
主要理解 getState,dispatch,subscribe 和 unsubscribe,replaceReducer 方法。

之前都只讲了单一 reducer 完成单一页面或者应用,但当应用变得复杂,如果还是用一个 reducer 去处理的话,那么必然会产生 switch N 多 N 多的case

那样既不美观也不利于性能。

所以将这些 N 多的 case 拆分到多个 reducer 去处理,每个 reducer 只管理应用中整个 state 中的部分属性,然后再用 combineReducer 最终再合成为一个 Reducer 入口,同时也就改变了 state 的结构,只有一个 state 包含了整个应用每个部分的状态。

state:{
   partA:{},
   partB:{},
   ....
}

combineReducer 用法:

var rootReducer = combineReducers({
  count: count,
  year: year,
});

看一下 combineReducer 关键源码(完整版自己搜索一下),理解是如何工作的:

export default function combineReducers(reducers) {  //参数为一个普通Object
var reducerKeys = Object.keys(reducers) //获取所有 Object 的 key 值数组
var finalReducers = {}//过滤后的可用 reducer  
for (var i = 0; i < reducerKeys.length; i++) { 
//遍历排除不合法的reducer   
......
 }  

//返回一个总的reducer闭包,它的初步调用是在creatStore中初始化状态时;
return function combination(state = {}, action) { 
......
var nextState={};
var hasChanged = false;
//遍历所有可用 reducer对象,然后执行reducer获取初始化状态,finalReducerKeys 为可用 reducer 的 key 值数组
for (var i = 0; i < finalReducerKeys.length; i++) {     
  var key = finalReducerKeys[i] //取一个 reducer 的 key    
  var reducer = finalReducers[key]   //通过 key 值找到对应的 reducer   
  var previousStateForKey = state[key]   //当前 reducer 的 state,作为这次reducer 的 initialState   
  var nextStateForKey = reducer(previousStateForKey, action)   //获取初始化状态 
  if (typeof nextStateForKey === 'undefined') { 
//reducer 返回 undefined,则报错       
    var errorMessage = getUndefinedStateErrorMessage(key, action)      
    throw new Error(errorMessage)      }     
  nextState[key] = nextStateForKey//问题一     
  hasChanged = hasChanged || nextStateForKey !== previousStateForKey    }  
// 判断初始化状态是否改变,返回对象的状态
  return hasChanged ? nextState : state 
 }}

首先明确一点,经过 combineReducer 捆绑后返回的是一个和 reducer 形式一直的函数 combination(state,action),其实也就是一个 reducer!

问题一:这里的 nextStateForKey 和 nextState[key]一定会变吗?

答案是不一定,其实每次调用 dispatch 的时候会把 action 发送到 rootReducer  中,然后遍历所有 reducer,返回其更新后的 state,

那么就可能是这个 action 的 type 不一定在这个 reducer 中找到对应的 case 进行修改,所以不一定会变,只有找到了对应的 type 才会执行相应的逻辑修改 state。


这里最重要的是,每一个 reducer 有专属自己的唯一 key 值,之后的所有操作都和 key 值"绑定"

以 key='count'为例,即reducer['count']返回的值赋到state[key]。


未完待续。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值