Redux
Redux 属于视图状态管理工具,它解决了传统 MVVM 架构的 VM 层状态管理责任过重的问题,他使用订阅发布的模式,将 VM 层的状态集中式的管理,这样做的好处有
- 视图通讯变得简单,多个视图可以轻松共用状态
- 代码分割更加简便
它有以下特点
- 不支持异步,派发 action 的过程中,没有实现
thunk
接口,不能实现阻塞 - 支持对 state 的 cbs(控制反转) 风格处理,reducer 为函数
开始撸一个 redux
我们建立一个redux
文件夹,然后在该目录创建一个index.js
import createStore from "./core/createStore";
export default createStore;
接下来我们来实现createStore
方法,在该目录下建立core
目录,并在该目录下建立createStore.js
文件,创建createStore
方法
createStore,创建一个
store
,一个redux
架构应该只有一个store
,该store
用于维持state
,派发action
,注册监听器,
redux 使用的是函数式编程,所以下面会用有一个闭包函数,执行后返回 redux 提供的 API
export default function createStore(reducer, preLoadState, enhancer) {
if (enhancer) {
// 中间件处理
return enhancer(createStore)(reducer, preLoadState);
}
function getState() {} // 获取state
function subscribe() {}
function dispatch() {}
function replaceReducer() {}
// 告诉控制台,初始化store 顺便触发reducer的default分支,拿到initialState
dispatch({ type: "REDUX_INIT" });
return {
getState,
subscribe,
dispatch,
replaceReducer,
};
}
A. getState (获取状态)
getState 用于获取 store 的 state,接下来我们来实现 getState
方法
export default function createStore(reducer, preLoadState, enhancer) {
let currentState = preLoadState;
function getState() {
if (isDispatching) {
throw new Error("你不能获取state,因为现在正在派发action");
}
return currentState;
}
// ...
}
B. dispatch (调度)
dispatch 方法用于派发一个 action,action 由type
与payload
组成
export default function createStore(reducer, preLoadState, enhancer) {
let isDispatching = false;
let currentReducer = reducer;
let currentListeners = [];
let nextListeners = currentListeners;
function dispatch(action) {
try {
isDispatching = true;
// 处理传入的action
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
}
currentListeners = nextListeners;
const listeners = currentListeners;
// 遍历订阅者,通知action已经派发完成
listeners.forEach((lisntener) => listener());
return action;
}
// ...
}
C. subscribe (订阅)
该方法用于提供给组件订阅 store 的变化,当 store 发生变化时,既可在订阅方法中更新视图
export default function createStore(reducer, preLoadState, enhancer) {
let isSubscribed = false;
let nextListeners = [];
function subscribe(listener) {
nextListeners.push(listener);
return function unsubscribe() {
if (!isSubscribed) {
return;
}
if (isDispatching) {
throw new Error("不能在派发action的时候,取消store的订阅");
}
isSubscribed = true;
// 可以直接通过indexOf进行函数的查找
const index = nextListeners.indexOf(listener);
// 删除缓存中的订阅函数
nextListeners.splice(index, 1);
};
}
// ...
}
D. replaceReducer (替换处理者)
用于替换 store 的 reducer 对象,这个方法没什么特别的
export default function createStore(reducer, preLoadState, enhancer) {
function replaceReducer(nextReducer) {
currentReducer = nextReducer;
// 告诉控制台,替换了reducer
dispatch({ type: "REDUX_REPLACE" });
}
// ...
}
结束
这样,我们就简单的撸完一个 redux 了,我们以 React 为例子,来看看如何使用它
// reducer
const reducer = (state = {}, action) => {
switch (action.tpye) {
case "TMD": {
// 对state进行处理
state.name = "干啥啥不行";
return state;
}
default: {
return state;
}
}
};
const store = createStore(reducer);
import React from "react";
class App extends React.Component {
constructor() {
super();
this.state = store.getState();
}
componentDidMount() {
this.unscribe = store.subscribe(() => {
this.setState(store.getState());
});
}
render() {
const styleObj = {
background: "#66ccff",
width: "200px",
color: "#fff",
textAlign: "center",
cursor: "pointer",
};
return (
<ul>
以下是model的数据 : <br />
<div style={styleObj} onClick={this.changeStore.bind(this)}>
点击这里改变store数据
</div>
{JSON.stringify(this.state.model)}
</ul>
);
}
}
网友评论