原理:
MyReduxPage:引入store,store.subscribe()订阅消息,store.dispatch()派发消息,store.getState()获取数据
counterReducer:传入state和action,返回新的state
kRedux.js:定义了createStore方法,传入了counterReducer和applyMiddleware(logger, thunk)。
createStore内部定义了以下函数:
getState() 返回当前值。
subscribe(listener) currentListeners数组保存传入的方法(listener就是传入的方法)
dispatch(action) 其实是调用了counterReducer,传入一个对象里面包含type值,根据类型返回新的state给currentState保存。遍历之前保存的currentListeners数组,执行监听的所有方法。
createStore方法内部主动调用一次dispatch,因为第一次传入没有定义的类型,所以state返回0
applyMiddleware()实现:applyMiddleware(logger, thunk)(createStore)(reducer),主要做的事情是,把counterReducer传给createStore重新创建没有enhancer的store,拿出store.getState和store.dispatch作为api对象,遍历[logger,thunk]数组,给里面的方法传入api对象,返回一个新的函数数组。compose封装了一次dispatch方法,当执行dispatch方法的时候,先执行thunk 再执行logger 再执行dispatch。
MyReduxStore.js: createStore创建store实例,定义logger和thunk函数。
当执行dispatch时 执行thunk(logger(dispatch))
src/pages/MyReduxPage.js
import React, { Component } from "react";
import store from "../store/MyReduxStore";
export default class MyReduxPage extends Component {
componentDidMount() {
store.subscribe(() => {
this.forceUpdate();
// this.setState({});
});
}
asyAdd = () => {
store.dispatch(dispatch => {
setTimeout(() => {
dispatch({ type: "add" });
}, 1000);
});
};
render() {
// console.log("store", store);
return (
<div>
<h1>MyReduxPage</h1>
<p>{store.getState()}</p>
<button onClick={() => store.dispatch({ type: "add" })}>add</button>
<button onClick={() => store.dispatch({ type: "minus" })}>minus</button>
<button onClick={this.asyAdd}>asyAdd</button>
</div>
);
}
}
src/store/MyReduxStore.js
import { createStore, applyMiddleware } from "../kRedux";
import { counterReducer } from "./counterReducer";
const store = createStore(counterReducer, applyMiddleware(logger, thunk));
function logger() {
return dispatch => action => {
action.type && console.log(action.type + "执行啦!");
return dispatch(action);
};
}
function thunk({ getState }) {
return dispatch => action => {
if (typeof action === "function") {
return action(dispatch, getState);
} else {
return dispatch(action);
}
//console.log(action.type + "执行啦!");
//return dispatch(action);
};
}
export default store;
src/kRedux.js
export function createStore(reducer, enhancer) {
if (enhancer) {
return enhancer(createStore)(reducer);
}
let currentState = undefined;
let currentListeners = [];
function getState() {
return currentState;
}
function dispatch(action) {
currentState = reducer(currentState, action);
currentListeners.map(lis => lis());
return action;
}
function subscribe(listener) {
currentListeners.push(listener);
}
dispatch({ type: "IMMOCC/KKKREDUX" });
return {
getState,
dispatch,
subscribe,
};
}
export function applyMiddleware(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args);
const midAPi = {
getState: store.getState,
dispatch: store.dispatch,
};
const middlewareChain = middlewares.map(mw => mw(midAPi));
const dispatch = compose(...middlewareChain)(store.dispatch);
return {
...store,
dispatch,
};
};
}
function compose(...funcs) {
const len = funcs.length;
if (len === 0) {
return arg => arg;
} else if (len === 1) {
return funcs[0];
} else {
return funcs.reduce((a, b) => (...args) => b(a(...args)));
}
}
src/store/counterReducer.js
export function counterReducer(state = 0, action) {
switch (action.type) {
case "add":
return state + 1;
case "minus":
return state - 1;
default:
return state;
}
}
网友评论