Top AI Repos — open-source AI, indexed and scored
Top AI Repos tracks AI repositories on GitHub and answers two different questions about each one: is it moving right now, and would you bet a product on it.
Top AI Repos tracks AI repositories on GitHub and answers two different questions about each one: is it moving right now, and would you bet a product on it.
Redux 简明教程。本教程深入浅出,配套入门、进阶源码解读以及文档注释丰富的 Demo 等一条龙服务
| Date | Stars |
|---|---|
| 2026-07-24 | 2608 |
| 2026-07-25 | 2608 |
| 2026-07-28 | 2608 |
| 2026-07-30 | 2608 |
| 2026-08-06 | 2608 |
Today
— stars today
This week
— stars this week
This month
— stars this month
Momentum
0.0
growth rate 0.00%/day
# Redux 简明教程
> 原文链接(保持更新):[https://github.com/kenberkeley/redux-simple-tutorial][this-github]
> ### 写在前面
> 本教程深入浅出,配套 简明教程、[进阶教程][advanced-tutorial](源码精读)以及文档注释丰满的 [Demo][react-demo] 等一条龙服务
## § 为什么要用 Redux
> 当然还有 [Flux][flux]、[Reflux][reflux]、[Mobx][mobx] 等状态管理库可供选择
抛开需求讲实用性都是耍流氓,因此下面由我扮演您那可亲可爱的产品经理
### ⊙ 需求 1:在控制台上记录用户的每个动作
不知道您是否有后端的开发经验,后端一般会有记录访问日志的**中间件**
例如,在 Express 中实现一个简单的 Logger 如下:
```js
var loggerMiddleware = function(req, res, next) {
console.log('[Logger]', req.method, req.originalUrl)
next()
}
...
app.use(loggerMiddleware)
```
每次访问的时候,都会在控制台中留下类似下面的日志便于追踪调试:
```
[Logger] GET /
[Logger] POST /login
[Logger] GET /user?uid=10086
...
```
如果我们把场景转移到前端,请问该如何实现用户的动作跟踪记录?
我们可能会这样写:
```js
/** jQuery **/
$('#loginBtn').on('click', function(e) {
console.log('[Logger] 用户登录')
...
})
$('#logoutBtn').on('click', function() {
console.log('[Logger] 用户退出登录')
...
})
/** MVC / MVVM 框架(这里以纯 Vue 举例) **/
methods: {
handleLogin () {
console.log('[Logger] 用户登录')
...
},
handleLogout () {
console.log('[Logger] 用户退出登录')
...
}
}
```
上述 jQuery 与 MV* 的写法并没有本质上的区别
记录用户行为代码的侵入性极强,可维护性与扩展性堪忧
### ⊙ 需求 2:在上述需求的基础上,记录用户的操作时间
> 哼!最讨厌就是改需求了,这种简单的需求难道不是应该一开始就想好的吗?
> 呵呵,如果每位产品经理都能一开始就把需求完善好,我们就不用加班了好伐
显然地,前端的童鞋又得一个一个去改(当然 编辑器 / IDE 都支持全局替换):
```js
/** jQuery **/
$('#loginBtn').on('click', function(e) {
console.log('[Logger] 用户登录', new Date())
...
})
$('#logoutBtn').on('click', function() {
console.log('[Logger] 用户退出登录', new Date())
...
})
/** MVC / MVVM 框架(这里以 Vue 举例) **/
methods: {
handleLogin () {
console.log('[Logger] 用户登录', new Date())
...
},
handleLogout () {
console.log('[Logger] 用户退出登录', new Date())
...
}
}
```
而后端的童鞋只需要稍微修改一下原来的中间件即可:
```js
var loggerMiddleware = function(req, res, next) {
console.log('[Logger]', new Date(), req.method, req.originalUrl)
next()
}
...
app.use(loggerMiddleware)
```
### ⊙ 需求 3:正式上线的时候,把控制台中有关 Logger 的输出全部去掉
难道您以为有了 UglifyJS,配置一个 `drop_console: true` 就好了吗?图样图森破,拿衣服!
请看清楚了,仅仅是去掉有关 Logger 的 `console.log`,其他的要保留哦亲~~~
于是前端的童鞋又不得不乖乖地一个一个注释掉(当然也可以设置一个环境变量判断是否输出,甚至可以重写 `console.log`)
而我们后端的童鞋呢?只需要注释掉一行代码即可:`// app.use(loggerMiddleware)`,真可谓是不费吹灰之力
### ⊙ 需求 4:正式上线后,自动收集 bug,并还原出当时的场景
收集用户报错还是比较简单的,[利用 `window.error` 事件][global-err-handler],然后根据 Source Map 定位到源码(但一般查不出什么)
但要完全还原出当时的使用场景,几乎是不可能的。因为您不知道这个报错,用户是怎么一步一步操作得来的
就算知道用户是如何操作得来的,但在您的电脑上,测试永远都是通过的(不是我写的程序有问题,是用户用的方式有问题)
相对地,后端的报错的收集、定位以及还原却是相当简单。只要一个 API 有 bug,那无论用什么设备访问,都会得到这个 bug
还原 bug 也是相当简单:把数据库备份导入到另一台机器,部署同样的运行环境与代码。如无意外,bug 肯定可以完美重现
> 在这个问题上拿后端跟前端对比,确实有失公允。但为了鼓吹 Redux 的优越,只能勉为其难了
>
> 实际上 jQuery / MV* 中也能实现用户动作的跟踪,用一个数组往里面 `push` 用户动作即可
> 但这样操作的意义不大,因为仅仅只有动作,无法反映动作前后,应用状态的变动情况
### ※ 小结
为何前后端对于这类需求的处理竟然大相径庭?后端为何可以如此优雅?
原因在于,后端具有**统一的入口**与**统一的状态管理(数据库)**,因此可以引入**中间件机制**来**统一**实现某些功能
多年来,前端工程师忍辱负重,操着卖白粉的心,赚着买白菜的钱,一直处于程序员鄙视链的底层
于是有大牛就把后端 MVC 的开发思维搬到前端,**将应用中所有的动作与状态都统一管理**,让一切**有据可循**
使用 Redux,借助 [Redux DevTools][redux-devtools] 可以实现出“华丽如时光旅行一般的调试效果”
实际上就是开发调试过程中可以**撤销与重做**,并且支持应用状态的导入和导出(就像是数据库的备份)
而且,由于可以使用日志完整记录下每个动作,因此做到像 Git 般,随时随地恢复到之前的状态
> 由于可以导出和导入应用的状态(包括路由状态),因此还可以实现前后端同构(服务端渲染)
> 当然,既然有了动作日志以及动作前后的状态备份,那么还原用户报错场景还会是一个难题吗?
## § Store
首先要区分 `store` 和 `state`
`state` 是应用的状态,一般本质上是一个普通**对象**
例如,我们有一个 Web APP,包含 计数器 和 待办事项 两大功能
那么我们可以为该应用设计出对应的存储数据结构(应用初始状态):
```js
/** 应用初始 state,本代码块记为 code-1 **/
{
counter: 0,
todos: []
}
```
`store` 是应用状态 `state` 的管理者,包含下列四个函数:
* `getState() # 获取整个 state`
* `dispatch(action) # ※ 触发 state 改变的【唯一途径】※`
* `subscribe(listener) # 您可以理解成是 DOM 中的 addEventListener`
* `replaceReducer(nextReducer) # 一般在 Webpack Code-Splitting 按需加载的时候用`
二者的关系是:`state === store.getState()`
Redux 规定,一个应用只应有一个单一的 `store`,其管理着唯一的应用状态 `state`
Redux 还规定,不能直接修改应用的状态 `state`,也就是说,下面的行为是不允许的:
```jsExcerpt of 10,712 characters
Read on GitHub3
2
Yu Xia · MyCase · United States
1
Would you bet a product on this? Bounded 0–100 and slow moving.
matched fp:0f5577382f207c78, topic:tutorial, name:tutorial, readme:tutorial