欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > React@16.x(56)Redux@4.x(5)- 实现 createStore

React@16.x(56)Redux@4.x(5)- 实现 createStore

2024/11/30 12:27:23 来源:https://blog.csdn.net/qq_40147756/article/details/140308134  浏览:    关键词:React@16.x(56)Redux@4.x(5)- 实现 createStore

目录

  • 1,分析
  • 2,实现
    • 2.1,基础实现
    • 2.2,优化
      • 2.2.1,随机字符串
      • 2.2.2,action 的判断
      • 2.2.2,监听器的优化
    • 2.3,最终形态
    • 2.4,关于 applyMiddleware 的补充代码

1,分析

createStore(),参数1为 reducer,参数2为初始化的 state(中间件参数,之后的文章会介绍)。返回的 store 对象有以下属性:

  • dispatch 方法,用于分发 action
  • getState 方法,用于得到最新的 state
  • subscribe 方法,用于在 state 发生变化时执行。

2,实现

2.1,基础实现

export const createStore = (reducer, defaultState) => {let currentReducer = reducer;let currentState = defaultState;let listeners = [];const dispatch = (action) => {currentState = currentReducer(currentState, action);// 每次更新时,遍历监听器。for (const listener of listeners) {listener();}};const getState = () => {return currentState;};const subscribe = (listener) => {listeners.push(listener);// 取消监听return () => {listeners = listeners.filter((f) => f !== listener);};};// createStore 创建时会调用一次。dispatch({type: "@@redux/INITg.p.0.c.e.f",});return {dispatch,getState,subscribe,};
};

2.2,优化

2.2.1,随机字符串

createStore 创建时调用 dispatch() 传入的 type 是随机 36位 字符串。可以这样生成:

Math.random().toString(36) // '0.ge0p9nwtid7'
Math.random().toString(36).substring(2, 8) // 'ge0p9n'
Math.random().toString(36).substring(2, 8).split('').join('.') // 'g.e.0.p.9.n'
export const createStore = (reducer, defaultState) => {// ...dispatch({type: `@@redux/INIT${getRandomString()}`,});// ...
};function getRandomString() {return Math.random().toString(36).substring(2, 8).split('').join('.')
}

2.2.2,action 的判断

action 有一些限制:

  • 必须是一个平面对象。
  • 必须有 type 属性。
const dispatch = (action) => {if (typeof action !== "object" || Object.getPrototypeOf(action) !== Object.prototype) {throw new Error("action 必须是一个 plain Object");}if (action.type === undefined) {throw new Error("action 必须有 type 属性");}// ...
};

2.2.2,监听器的优化

监听器返回的函数执行一次之后,再次执行时应该立即返回且什么都不做。因为对应的监听器已经卸载了。

const subscribe = (listener) => {listeners.push(listener);let isRemove = false;return () => {if (isRemove) {return;} else {isRemove = true;listeners = listeners.filter((f) => f !== listener);}};
};

2.3,最终形态

export const createStore = (reducer, defaultState) => {let currentReducer = reducer;let currentState = defaultState;let listeners = [];const dispatch = (action) => {if (typeof action !== "object" || Object.getPrototypeOf(action) !== Object.prototype) {throw new Error("action 必须是一个 plain Object");}if (action.type === undefined) {throw new Error("action 必须有 type 属性");}currentState = currentReducer(currentState, action);// 每次更新时,遍历监听器。for (const listener of listeners) {listener();}};const getState = () => {return currentState;};const subscribe = (listener) => {listeners.push(listener);let isRemove = false;// 取消监听return () => {if (isRemove) {return;} else {isRemove = true;listeners = listeners.filter((f) => f !== listener);}};};// createStore 创建时会调用一次。dispatch({type: `@@redux/INIT${getRandomString}`,});return {dispatch,getState,subscribe,};
};function getRandomString() {return Math.random().toString(36).substring(2, 8).split("").join(".");
}

2.4,关于 applyMiddleware 的补充代码

参考 实现 applyMiddleware。


以上。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com