TodoMVC React-Redux 示例深度解析Redux 单向数据流与 Webpack 工程化实践【免费下载链接】todomvcHelping you select a JavaScript framework - Todo apps for React.js, Angular, Vue and many more项目地址: https://gitcode.com/gh_mirrors/to/todomvc本文基于 TodoMVC 仓库中的 examples/react-redux/README.md 展开系统讲解该示例如何用 React Redux React-Redux 三件套实现标准 TodoMVC 应用并结合 store 定义、组件实现 与 Webpack 构建配置 还原其数据流、组件连接关系与构建流程读完可掌握 Redux Toolkit 的 slice/selectors 组织方式与 TodoMVC 官方应用的工程化构建链路。应用定位React、Redux 与 React-Redux 的分工官方 README 对该示例的定位是这是一个使用 React 结合 Redux 实现的 TodoMVC 应用三个核心依赖各有明确职责React用于创建用户界面的 JavaScript 库Redux负责集中管理应用状态centralize stateReact-Redux让 Redux 与 React 的组件模型协作把 store 接入组件树。从 examples/react-redux/package.json 可以看到当前仓库锁定的实际依赖版本react与react-dom为 19.xreact-redux为 9.x状态管理基于reduxjs/toolkit2.x并引入了react-router-dom7.x 用于过滤路由todomvc-app-css与todomvc-common提供官方统一的界面样式与测试工具。数据流设计Redux 视角下的 MVC 映射README 的“Implementation details”部分给出了这段实现的核心设计哲学Redux 模式类似于 MVC 模式主要区别在于 Redux 是单向unidirectional数据流。其完整流程为Redux 用actions发出一次变更请求reducers捕获 action 并更新中央 storestore 中的状态更新后View收到新状态并向用户呈现变化。README 进一步给出了 Redux 与经典 MVC 的逐项对应关系这是理解该示例代码结构的关键角色Redux 实现MVC 中的角色ModelRedux store维护应用的数据与行为ViewReact UI 组件在界面中展示模型ControllerReact connected components Redux reducers作为视图与模型之间的接口Store 层用 createSlice 集中定义状态与动作按上述映射Model 的全部实现集中在 examples/react-redux/src/store.js。该文件用 Redux Toolkit 的createSlice定义了一个名为todos的 slice初始状态是空数组[]并包含 6 个 reducer源码 L3-L36Action行为源码细节addTodo向数组尾部追加新 todo使用prepare回调在派发动作时生成{ id: nanoid(), text, completed: false }载荷L7-L14用nanoid生成唯一 iddeleteTodo按 id 过滤删除state.filter((todo) todo.id ! action.payload)editTodo更新指定 todo 的文本先find找到目标再改写texttoggleTodo翻转单个 todo 的完成状态todo.completed !todo.completedtoggleAll全部完成则全部取消否则全部完成通过state.every((todo) todo.completed)判断当前是否已全部完成再批量翻转clearCompleted清除所有已完成的 todostate.filter((todo) !todo.completed)这些 action 在 L38 被统一解构导出供各组件dispatch调用。store 本身由configureStore创建todos作为唯一顶层 reducerL40-L42印证了 README 所说的中央 store设计。派生状态过滤器与 selectorsREADME 强调状态更新后视图能反映变化TodoMVC 的过滤All / Active / Completed正是派生状态的典型场景。store.js 中没有把过滤结果写入 state而是用 selector 即时计算L44-L55FILTERS是路径到过滤函数的映射/与/all返回全部、/active只留未完成项、/completed只留已完成项selectVisibleTodos(pathname)返回一个接收state的 selector根据当前路由路径应用对应过滤函数selectCompletedCount统计已完成数量selectTodos直接读取state.todos。这种原始状态 派生 selector的组织方式使得过滤逻辑完全由路由路径驱动组件侧无需维护额外的 UI 状态。组件层Provider 挂载与 connected components入口把 store 注入组件树examples/react-redux/src/index.js 是应用入口L11-L17createRoot(document.getElementById(root)).render( Provider store{store} HashRouter App / /HashRouter /Provider );这里体现了两个关键决策Provider将 store 注入整棵组件树任何子组件都可通过useDispatch/useSelector访问状态——这就是 README 中React-Redux 与 React 组件模型协作的具体落点HashRouter使用哈希路由#/、#/active、#/completed与 public/index.html 中静态页面的定位方式一致无需服务器端路由配置。入口同时引入todomvc-app-css/index.css与todomvc-common/base.css保证界面遵循 TodoMVC 官方视觉规范。App 与页面骨架app.jsx 结构极简仅由Header /与Main /两个区块组成对应 TodoMVC 规范的输入区与主体区section classtodoapp idroot作为挂载点声明在 public/index.html 中并带有data-frameworkreact-redux标记。Header派发动作的起点header.jsx 展示了发出 action一侧的典型写法通过useDispatch()获取 dispatch 函数在输入框保存回调里调用dispatch(addTodo(text))并对空文本做拦截。数据流由此启动组件 → action → reducer → store。Main消费状态的 connected componentmain.jsx 是View 接收新状态的典型代表它同时消费状态useSelector与发出动作useDispatchuseSelector(selectTodos)取全量列表用于计算activeCount与空状态判断useSelector(selectVisibleTodos(location.pathname))配合useLocation()让可见列表随路由路径实时切换——过滤器链接点击后 URL 变化selector 重算列表随之更新这正是 README 所述store 更新 → view 呈现变化闭环的过滤场景实现Toggle All 复选框的checked由completedCount todos.length派生onChange派发toggleAll()。Item 与 TextInput局部状态与 Redux 状态的边界item.jsx 展示了状态划分的细节是否处于编辑态属于组件私有状态useState管理editing而 todo 本身的数据变更全部走 ReduxtoggleTodo/editTodo/deleteTodo。编辑保存时的规则值得注意文本为空则dispatch(deleteTodo(todo.id))否则dispatch(editTodo({ id, text }))。此外该组件用memo包裹配合不可变更新减少列表项重渲染。footer.jsx 消费父组件传入的计数 props 与location.pathname渲染剩余项数、三个过滤链接#/、#/active、#/completed以及Clear completed按钮派发clearCompleted()。text-input.jsx 是唯一不直接接触 Redux 的组件它通过onSave/onCancel回调把职责交给调用方处理 Enter 提交、Escape 取消编辑态与失焦保存等行为是一个纯 UI 的可复用控件。存储方案纯内存数组README 明确指出存储方案使用一个内存数据对象实现一个简单数组来保存 todos。 源码完全印证了这一点store.js 的initialState: []就是唯一的初始状态没有任何 localStorage 读写或网络同步逻辑每次 reducer 执行后数组被替换或改写状态只存在于 store 生命周期内刷新页面即清空。选择纯内存存储是刻意的取舍——TodoMVC 示例的核心目标是演示框架的状态管理模式而非持久化方案。若要在真实项目中扩展可在此基础上接入持久化中间件或 Toolkit 的configureStore序列化能力但当前仓库实现中并不包含这部分。构建流程Webpack 三段式配置README 的Build steps说明构建静态文件使用 webpack它会压缩并优化输出文件并把所有必要文件拷贝到dist目录。仓库中这由三个配置文件协作完成公共配置入口、模板与转译webpack.common.js 定义了基础链路入口src/index.jsL5-L7HTML 模板HtmlWebpackPlugin以public/index.html为模板生成最终页面L9-L12输出dist/[name].bundle.js并开启clean: true保证每次构建前清空输出目录L14-L18转译babel-loader处理js/jsx文件配置babel/preset-envtargets: defaults与babel/preset-reactruntime: automatic即无需手动import React的新 JSX 运行时L24-L36静态资源图片类走asset/resource类型处理L38-L40。开发配置热更新与内联源码映射webpack.dev.js 通过webpack-merge合并公共配置后追加mode: development、devtool: inline-source-map便于调试CSS 走style-loadercss-loader以 JS 注入样式支持热更新devServer.static: ./dist指定静态服务目录。生产配置压缩、抽离与拷贝webpack.prod.js 对应 README 中minifies and optimizes的描述MiniCssExtractPlugin把 CSS 从 JS 中抽离为独立的[name].css文件CopyPlugin将node_modules/todomvc-common/base.js拷贝到输出根目录L17-L21——这正是 public/index.html 中script src./base.js的来源用于 TodoMVC 测试工具识别当前框架optimization.minimize开启压缩minimizer 为CssMinimizerPlugin与TerserPlugin分别负责 CSS 与 JS 的压缩devtool: source-map生成独立映射文件。运行要求与本地预览环境要求README 给出的最低环境要求为Node (min version: 18.13.0) NPM (min version: 8.19.3)唯一前提是安装 Node以便安装依赖并运行脚本启动本地服务器。需要补充一点package.json 的engines字段当前声明为node 20.19.0、npm 10.0.0L6-L9比 README 写的下限更严格按 npm 的 engines 校验行为建议在 Node 20 环境下运行以避免与锁定依赖如 React 19、Webpack 5.106出现兼容性问题。npm scripts 一览package.json 定义了三个脚本L10-L14脚本命令作用npm run buildwebpack --config webpack.prod.js走生产配置产出压缩后的dist静态文件npm run devwebpack serve --open --config webpack.dev.js启动 webpack-dev-server 并自动打开浏览器npm run servehttp-server ./dist -p 7002 -c-1 --cors用 http-server 以 7002 端口、禁用缓存-c-1、开启 CORS 的方式静态托管构建产物本地预览步骤README 给出的标准流程terminal: 1. npm install 2. npm run dev browser: 1. http://localhost:7001/即在examples/react-redux目录下安装依赖后启动开发服务器浏览器访问本地地址即可查看应用。其中dev脚本使用webpack serve --open会自动打开页面注意 webpack.dev.js 的devServer配置只显式指定了static: ./dist目录、未显式写死端口实际访问端口以启动时 dev-server 控制台输出或项目约定为准README 记录的入口地址为http://localhost:7001/。构建后如需静态托管可运行npm run serve直接服务dist目录。小结这个示例完整地演示了 README 所述的设计原则Redux 单向数据流替代了传统 MVC 的双向耦合——store.js 以 slice selectors 承担 Modelheader.jsx、main.jsx、item.jsx、footer.jsx 作为 connected components 承担 Controller 与 View 的混合职责存储采用纯内存数组刻意剥离持久化复杂度构建侧则用 webpack 三段式配置common/dev/prod实现了开发期热更新与生产期压缩抽离的分离。对学习者而言它可以作为理解 Redux Toolkit slice 组织、selector 派生状态、React-Redux hooks 连接方式以及 TodoMVC 规范 UI 结构的一个小而完整的参照实现。【免费下载链接】todomvcHelping you select a JavaScript framework - Todo apps for React.js, Angular, Vue and many more项目地址: https://gitcode.com/gh_mirrors/to/todomvc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
