redux
- 用于在项目中统一处理公用的状态
import { createStore } from 'redux';
/**
* 本质上是一个普通的函数
* @param {*} state: 之前的数据
* @param {*} action: 描述要干嘛的对象
*/
function reducer(state = 0, action) {
// 返回一个新的状态
switch(action.type) {
case "increase":
return state + 1;
case "decrease":
return state - 1;
default:
return state;
}
}
const store = createStore(reducer)
export default store;
import React, { Component } from 'react'
import store from '../store/index'
export default class ReduxDemo extends Component {
unsubscribe = null;
componentWillUnmount() {
// 取消订阅
this.unsubscribe();
}
componentDidMount() {
// 告诉redux,一旦state更新就刷新渲染
this.unsubscribe = store.subscribe(() => {
this.forceUpdate();
});
}
add = () => {
store.dispatch({type: "increase"})
}
render() {
return (
<div>
<h1>{ store.getState() }</h1>
<button onClick={this.add}>add</button>
</div>
)
}
}
基础源码
function createStore(reducer) {
let currentState;
let currentListeners = [];
// 获取值
function getState() {
return currentState;
}
function dispatch(action) {
currentState = reducer(currentState, action);
currentListeners.forEach(listener => listener());
}
// 订阅后渲染组件
function subscribe(listener) {
currentListeners.push(listener);
return () => {
const index = currentListeners.indexOf(listener);
currentListeners.splice(index, 1);
}
}
// 帮用户先渲染一次
dispatch({type: "@@@@redux-cccc"})
return {
getState,
dispatch,
subscribe
}
}
export default {
createStore
}
// import { createStore } from 'redux';
import { createStore } from '../myRedux/redux'
/**
* 本质上是一个普通的函数
* @param {*} state: 之前的数据
* @param {*} action: 描述要干嘛的对象
*/
function reducer(state = 0, action) {
// 返回一个新的状态
switch(action.type) {
case "increase":
return state + 1;
case "decrease":
return state - 1;
default:
return state;
}
}
const store = createStore(reducer)
export default store;
- 组件使用
import React, { Component } from 'react'
import store from '../store/index'
export default class ReduxDemo extends Component {
unsubscribe = null;
componentWillUnmount() {
// 取消订阅
this.unsubscribe();
}
componentDidMount() {
// 告诉redux,一旦state更新就刷新渲染
this.unsubscribe = store.subscribe(() => {
this.forceUpdate();
});
}
add = () => {
store.dispatch({type: "increase"})
}
minus = () => {
store.dispatch({type: "decrease"})
}
render() {
return (
<div>
<h1>{ store.getState() }</h1>
<button onClick={this.add}>add</button>
<button onClick={this.minus}>minus</button>
</div>
)
}
}
效果如下:
进一步完善版本
/**
* 判断某个对象是一个plain-object(平面对象)
* @param {*} obj
*/
function isPlainObject(obj) {
if(typeof obj !== "object") return false;
return Object.getPrototypeOf(obj) === Object.prototype;
}
/**
* 得到指定长度的随机字符串
* @param {Number} length
*/
function getRandomString(length) {
let RandNum = Math.random();
return RandNum.toString(36).slice(2, length).split("").join(".");
}
export function createStore(reducer, defaultState) {
let currentReducer = reducer,
currentState = defaultState,
currentListeners = [];
// 获取值
function getState() {
return currentState;
}
function dispatch(action) {
// 验证action
if(!isPlainObject(action)) {
throw new Error("action must a plain object");
}
// 验证action的type属性是否存在
if (action.type === undefined) {
throw new Error('action must has a prop');
}
currentState = currentReducer(currentState, action);
currentListeners.forEach(listener => listener());
}
// 订阅后渲染组件
function subscribe(listener) {
currentListeners.push(listener);
let isRemove = false;//是否已经移除
// 解除监听
return () => {
if (isRemove) return;
// 将之前添加的listener从数组中移除
const index = currentListeners.indexOf(listener);
currentListeners.splice(index, 1);
isRemove = true;
}
}
// 创建仓库时,帮用户先初始化一次
dispatch({type: `@@redux/Init${getRandomString(7)}`});
return {
getState,
dispatch,
subscribe
}
}
处理中间件的
/**
* 判断某个对象是一个plain-object(平面对象)
* @param {*} obj
*/
function isPlainObject(obj) {
if(typeof obj !== "object") return false;
return Object.getPrototypeOf(obj) === Object.prototype;
}
/**
* 得到指定长度的随机字符串
* @param {Number} length
*/
function getRandomString(length) {
let RandNum = Math.random();
return RandNum.toString(36).slice(2, length).split("").join(".");
}
export function createStore(reducer, enhancer) {
// 加强器 -> 加强了dispatch
if (enhancer) {
return enhancer(createStore)(reducer);
}
let currentReducer = reducer,
currentState,
currentListeners = [];
// 获取值
function getState() {
return currentState;
}
function dispatch(action) {
// 验证action
if(!isPlainObject(action)) {
throw new Error("action must a plain object");
}
// 验证action的type属性是否存在
if (action.type === undefined) {
throw new Error('action must has a prop');
}
currentState = currentReducer(currentState, action);
console.log(currentState);
currentListeners.forEach(listener => listener());
}
// 订阅后渲染组件
function subscribe(listener) {
currentListeners.push(listener);
let isRemove = false;//是否已经移除
// 解除监听
return () => {
if (isRemove) return;
// 将之前添加的listener从数组中移除
const index = currentListeners.indexOf(listener);
currentListeners.splice(index, 1);
isRemove = true;
}
}
// 创建仓库时,帮用户先初始化一次
dispatch({type: `@@Redux/Init${getRandomString(7)}`});
return {
getState,
dispatch,
subscribe
}
}
export function applyMiddleware(...middlewares) {
// 给我创建仓库的函数
return (createStore) => (reducer) => {
const store = createStore(reducer);
let dispatch = store.dispatch;
// todo 加强dispath
const midAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
// 新的中间件数组
const middlewareChain = middlewares.map(middleware => middleware(midAPI));
// 加强版dispath -> 把所有中间函数执行后,同时还执行 store.dispatch
dispatch = compose(...middlewareChain)(store.dispatch);
return {
...store,
// 加强版的dispatch
dispatch
}
}
}
function compose(...func) {
let len = func.length;
if (len === 0) {
return (func) => func;
}
if (len === 1) {
return func[0];
}
return func.reduce(
(a, b) =>
(...args) =>
a(b(...args))
);
}
如下图:所示