继上一篇: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