前言
本文从将从Redux原理出发,一步步自己实现一个简单的Redux,主要目的是了解Redux内部之间的联系。看本文之前先要知道Redux是怎么用的,对Redux用法不会讲解太多。
Redux介绍
首先要知道的是,Redux 和 React 没有关系,Redux 可以用在任何框架中。
Redux 是一个JavaScript 状态管理器,是一种新型的前端“架构模式”。
还有通常与redux一起用的一个库——react-redux, 它就是把 Redux 这种架构模式和 React.js 结合起来的一个库,就是 Redux 架构在 React.js 中的体现。
设计思想
- Web 应用是一个状态机,视图与状态是一一对应的。
- 所有的状态,保存在一个对象里面。
何时使用Redux
- 用户的使用方式复杂
- 不同身份的用户有不同的使用方式(比如普通用户和管理员)
- 多个用户之间可以协作
- 与服务器大量交互,或者使用了WebSocket
- View要从多个来源获取数据
从组件的角度看:
- 某个组件的状态,需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
Redux工作流程
![](https://oss.jqhtml.com/wp-content/uploads/2020/7/ieiU3e.png)
- Redux 将整个应用状态(state)存储到一个地方(通常我们称其为 store)
- 当我们需要修改状态时,必须派发(dispatch)一个 action( action 是一个带有 type 字段的对象)
- 专门的状态处理函数 reducer 接收旧的 state 和 action ,并会返回一个新的 state
- 通过 subscribe 设置订阅,每次派发动作时,通知所有的订阅者。
从这个流程中可以看出,Redux 的核心就是一个 观察者 模式。一旦 store 发生了变化就会通知所有的订阅者,视图(在这里是react组件)接收到通知之后会进行重新渲染。
Redux案例
为了简化说明,我用和官网差不多的例子改写来作案例官网redux demo
新建一个文件redux.js,然后直接引入,观察控制台输出
import { createStore } from 'redux'
const defaultState = {
value: 10
}
// reducer处理函数
function reducer (state = defaultState, action) {
console.log(state, action)
switch (action.type) {
case 'INCREMENT':
return {
...state,
value: state.value + 1
}
case 'DECREMENT':
return {
...state,
value: state.value - 1
}
default:
return state
}
}
const store = createStore(reducer)
const init = store.getState()
console.log(`一开始数字为:${init.value}`)
function listener () {
const current = store.getState()
console.log(`当前数字为:${current.value}`)
}
store.subscribe(listener) // 监听state的改变
store.dispatch({ type: 'INCREMENT' })
// 当前数字为:11
store.dispatch({ type: 'INCREMENT' })
// 当前数字为:12
store.dispatch({ type: 'DECREMENT' })
// 当前数字为:11
export default store
输出结果:
{value: 10} {type: "@@redux/INIT1.a.7.g.7.t"}
一开始数字为:10
{value: 10} {type: "INCREMENT"}
当前数字为:11
{value: 11} {type: "INCREMENT"}
当前数字为:12
{value: 12} {type: "DECREMENT"}
当前数字为:11
所有对数据的操作必须通过 dispatch 函数,它接受一个参数action,action是一个普通的JavaScript对象,action必须包含一个type
字段,告诉它要修改什么,只有它允许才能修改。
在每次调用进来reducer函数我们都打印了state和action,我们手动通过store.dispatch方法派发了三次action,但你会发现输出了四次.这是因为Redux内部初始化就自动执行了一次dispatch方法,可以看到第一次执行它的type对我们数据来说是没有影响的(因为type取值@@redux/INIT1.a.7.g.7.t
,我们自己redux的数据type不会取名成这个样子&