当前位置: 首页 > news >正文

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。


以上。

相关文章:

  • 基于IDEA的Lombok插件安装及简单使用
  • ARM 虚拟机FVP环境搭建
  • 2024-07-15 Unity插件 Odin Inspector4 —— Collection Attributes
  • 电脑的D盘E盘F盘突然消失了 电脑只剩下C盘了其他盘怎么恢复
  • C#中简单Socket编程
  • 中国电子学会青少年编程等级考试真题下载
  • Linux FFmpeg安装教程
  • 探索深度学习与Transformer架构的最新进展
  • STM32F103RC使用HAL库配置USART进行数据收发
  • 计算机图形学入门28:相机、透镜和光场
  • sysbench测试系统磁盘读写
  • 【开源项目】Rust开发复制文件夹目录结构工具
  • 新款S32K3 MCU可解决汽车软件开发的成本和复杂性问题(器件编号包含S32K322E、S32K322N、S32K328)
  • 【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会
  • 秋招突击——7/12——复习{每日温度、完全平方数、无重复最长子串}——新作{字节面试——控制多线程按照顺序输出}
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 2017-09-12 前端日报
  • AHK 中 = 和 == 等比较运算符的用法
  • Angular 2 DI - IoC DI - 1
  • java8-模拟hadoop
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • MySQL几个简单SQL的优化
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • node和express搭建代理服务器(源码)
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 从零开始在ubuntu上搭建node开发环境
  • 读懂package.json -- 依赖管理
  • 面试总结JavaScript篇
  • 算法系列——算法入门之递归分而治之思想的实现
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 云大使推广中的常见热门问题
  • 责任链模式的两种实现
  • 7行Python代码的人脸识别
  • Semaphore
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (LeetCode) T14. Longest Common Prefix
  • (八)Flask之app.route装饰器函数的参数
  • (备忘)Java Map 遍历
  • (二)斐波那契Fabonacci函数
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (原創) 物件導向與老子思想 (OO)
  • (转)3D模板阴影原理
  • (转)VC++中ondraw在什么时候调用的
  • (自用)仿写程序
  • .NET Core WebAPI中封装Swagger配置
  • .NET delegate 委托 、 Event 事件,接口回调
  • .Net Web窗口页属性
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .netcore 获取appsettings
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰
  • .net专家(张羿专栏)
  • /bin/rm: 参数列表过长"的解决办法