Redux概述
Redux是一种用来对数据状态进行管理的JavaScript应用工具,随着SPA单页面应用的复杂化,JavaScript需要管理的状态愈来愈多。这时,Redux应运而生,用来降低状态管理的复杂程度。接下来通过一张图来简单介绍redux是如何减低状态管理的复杂程度。(该图片来源于网上,如有侵权,请联系删除)

右边是使用了redux的组件传值。在redux中所有组件的数据都放在store中,在组件中少放或者不放数据。这个时候深蓝色组件与其他通信,只需改变store里面的数据,其他组件会自己感知store发生变化,自动去取store里面的数据,这样蓝色组件就非常轻松的将数据传递到其他组件。
Redux工作流程
1.Redux工作流程简述
接下来通过官方提供的一张图,我尝试解释一下redux的工作流程。

2.安装Redux
npm install redux --save
3.创建store
在store文件夹下创建一个index.js文件 store仅仅是一个仓库,它不具备管理能力,将接收到的action自动转发给reducer。
import { createStore } from 'redux' // 引入Redux
import reducer form 'reducer'
const store = createStore(reducer) // 创建一个数据仓库
export default store // 将store暴露出去
4.创建action
要想改变Redux里面state数据的值,就需要创建一个action,action是一个对象,里面一般有两个属性,第一个是action的描述,第二个是想要改变的值,然后再通过dispatch()方法传递给store。
import React from 'react'
import store from "./store"
import { Input, Button } from 'antd'
import 'antd/dist/antd.css'
class Test extends React.Component{
constructor(props) {
super(props)
// 通过store.getState()获取store里面的数据
this.state = store.getState()
// 改变this的指向
this.handlerInput = this.handlerInput.bind(this)
}
render() {
return (
<div>
<Input
value={this.state.inputValue}
onChange={this.handlerInput}
/>
</div>
)
}
handlerInput(e){
const action = {
type: 'change_value',
value: e.target.value
}
store.dispatch(action)
}
}
5.创建reducer
// 这个文件就相当于是上图中的reducers部分
// 定义一个默认值
const defaultState = {
inputValue: ''
}
// 这个方法接收两个参数,一个是state所有需要管理的原始数据信息
// 一个是action,指的是action传递的新状态
// 注意:reducer可以接收state,但是绝不能直接改变state,改变state还是store中
export default (state = defaultState, action) => {
if (action.type === 'change_value') {
const newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue = action.value
return newState
}
return state
}
通过以上几个步骤,便可实现一个简单的Redux流程。通过上面的方式会存在一些问题:
-
在开发过程中,肯定会派发多个action,这样就会造成一系列问题。如果不统一管理,可能会造成代码难以维护。action中的type必须要跟reducer里面action的type保持一致,如果名称不一致,浏览器不会报错,这样很难定位bug的位置。
-
对于逻辑复杂的组件,可能会存在很多action,将这些action都放在一个组件里面,很非常冗余,导致代码可读性差。
代码优化
针对以上的问题,我们应当采取统一的管理方式,这样可以提高代码的可读性、可维护性也会非常高。
1.创建一个store文件夹,在里面创建一个actionTypes.js文件
export const CHANGE_INPUT = 'CHANGE_INPUT'
2.在store文件夹下创建一个actionCreators.js文件
import {CHANGE_INPUT} form './actionTypes'
export const changeInput = (value) => ({
type: CHANGE_PAGE,
value
})
3.对action部分代码稍作改动
import React from 'react'
import store from "./store"
import { Input, Button } from 'antd'
import 'antd/dist/antd.css'
import {CHANGE_INPUT} form './actionTypes'
import {CHANGE_INPUT} form './actionCreators'
class Test extends React.Component{
constructor(props) {
super(props)
// 通过store.getState()获取store里面的数据
this.state = store.getState()
// 改变this的指向
this.handlerInput = this.handlerInput.bind(this)
}
render() {
return (
<div>
<Input
value={this.state.inputValue}
onChange={this.handlerInput}
/>
</div>
)
}
handlerInput(e){
const action = changeInput(e.target.value)
store.dispatch(action)
}
}
4.reducer部分
import {CHANGE_INPUT} form './actionTypes'
// 这个文件就相当于是上图中的reducers部分
// 定义一个默认值
const defaultState = {
inputValue: ''
}
// 这个方法接收两个参数,一个是state所有需要管理的原始数据信息
// 一个是action,指的是action传递的新状态
// 注意:reducer可以接收state,但是绝不能直接改变state,改变state还是store中
export default (state = defaultState, action) => {
if (action.type === 'CHANGE_INPUT') {
const newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue = action.value
return newState
}
return state
}
Redux注意事项
- store是必须唯一的,只能有一个store仓库
- 只有store能改变数据,reducer不能直接改变数据。reducer只是做了一个返回,并未真正改变数据,在store拿到reducer返回的数据之后,自己对自己做了改变,然后再更新到页面上。
- reducer里面必须是一个纯函数,所谓的纯函数就是给定固定的输入,就一定会有固定的输出,且不会有任何的副作用。