深入浅出Redux(一):通俗理解Redux

组内技术生态是React,参与使用React构建的大型项目也有几个了,趁着最近需求比较不饱和,来梳理一下常和React配套使用的数据流框架Redux的使用方法和内部原理。

阅读本文可以了解

  1. redux基本使用
  2. redux思想

前言

首先来了解下Redux能为我们解决什么痛点。

一般来说,如果我们一个小型应用,那么需要维护的状态(数据)可能只有几个,比如Todolist,需要关注的状态(数据)就只有todolist这个数组对象。数据间不需要多页面共享,这个时候在页面中直接定义state就行,根本没必要用上状态管理框架。

而如果我们的应用相当复杂,比如购物商城这种,需要关注的状态可能有 用户信息/购物车 等,而且用户信息可能在多个页面都需要用到,这时候使用状态管理框架维护一套唯一的State就显得非常有必要了。

对于不太了解Redux思想的前端(小白)ers来说,刚使用 Redux 的时候应该会感觉到不及 Vuex 易用。诚然,Redux里面有太多的新概念,比如Store/Reducer/Action/Action creator,并且上述的诸个概念在使用时又环环相扣,时常会让我们一头雾水。下文笔者会用相对于通俗的语言阐述下这几个概念以及用法。注意本文例子只使用纯 Redux 开发,暂不加入 react-redux 库和中间件。

Redux工作流

  1. 创建唯一Store作为整个应用共享的状态(数据)
  2. 创建改变Store的指令Action,注意Action只是对像
  3. 使用Reducer(函数)改变Store,根据Actiontype执行不同的操作

所以Redux三大概念的实质即是

  1. Store:数据对象
  2. Action:指令对象
  3. Reducer:纯函数

Action creator则是返回Action的函数,项目中一般是使用Action creator创建Action指令

突然发现Redux的思想被三言两语解释完了。。想当初可是理解了好久。。再举一个生活中的例子解释吧。

比如有一天你和小女友突然想玩玩过家家煮饭仔。
而家里有小白菜,鸡蛋。(相当于Store)小女友还想吃牛肉、茄子。
于是你:收到小女友指令:买牛肉/买茄子。(相当于Action
然后你:1. 去了菜市场>找到牛肉铺>给钱>买了牛肉>回家(action.type === 买牛肉)2. 去了菜市场>找到茄子铺>给钱>买了茄子>回家(action.type === 买茄子)(相当于Reducer

这时候家里库存就多了牛肉、茄子两个菜品。成功完成了小女友指令~~

现在估计对这三大概念就一定了解了,那我接着往深入讲。

demo

现在通过一个demo来了解Redux的具体使用方法

1、创建store:createStore

相当简单,只是调用一个API的事,需要传入reducer函数

1
2
3
4
5
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store

2、发出指令通知并执行相应reducer:dispatch

可以在View中绑定不同方法来发出指令告知Store执行reducer变更数据

使用store.dispatch(action)通知reducer根据指令执行方法
注意这里Redux帮我们包装过,只需dispath(action)无需手动执行reducer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// ./redux/action.js
// 这里的方法即 Action Creator
export const add = () => {
// 返回一个 Action 对象
return { type: 'add' }
}
// 同上
export const minus = () => {
return { type: 'minus' }
}
// App.js
import store from './redux/store'
import { add, minus } from './redux/action'
...
doAdd () {
store.dispatch(add())
}
doMinus () {
store.dispatch(minus())
}
...
<div><button onClick={this.doAdd}>+</button><button onClick={this.doMinus}>-</button></div>
// 看一眼具体的reducer
const initState = {
num: 0
}
const count = (state = initState, action) => {
switch (action.type) {
case 'add':
return {
...state,
num: ++state.num
}
case 'minus':
return {
...state,
num: --state.num
}
default:
return state
}
}
export default count

3、更新视图:subscribe

执行了store.dispatch(action)之后,其实Store的数据已经更新了,那么怎么告知视图作出更新呢?Redux为我们提供了subscribe方法,subscribe可以在任意时刻为Store订阅listener,然后在dispatch时执行listener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// App.js
...
componentDidMount () {
store.subscribe(() => {
// 更新应用的state
this.setState({
num: store.getState().num
})
})
}
...
// state 改变会再次执行render函数,修改页面中绑定的`num`
render() {
const { num } = this.state
return (
<div className="App">
<div>{num}</div>
<div><button onClick={this.doAdd}>+</button><button onClick={this.doMinus}>-</button></div>
</div>
)
}

于是。。深入浅出Redux第一篇就讲完了。。感谢阅读
2018-06-21-19-38-41