zzzmj/duola-blog

Redux基础

Opened this issue · 0 comments

zzzmj commented

1. Redux

Redux 的工作流程图

2. Redux基本原则

Redux三个基本原则

  • 单一数据源
  • 保持状态只读
  • 数据改变只能通过纯函数完成

2.1 单一数据源

单一数据源的意思是应用的数据状态只存储在一个唯一的Store中

2.2 保持状态只读

保持状态只读,意思就是不要去修改状态,要修改Store的状态,只能通过派发一个action对象完成

思考:驱动用户界面更改的是状态,状态只读,那怎么能引起用户界面的改变呢?

答:当然要改,只是我们不去修改状态值,而是创建一个新的状态对象给Redux,由Redux完成新状态的组装

2.3 数据改变只能通过纯函数

这里说的纯函数是Reducer

reducer(state, action)

第一个参数state是当前的状态
第二个参数action是接收到的action对象,而reducer函数要做的事情,就是根据state和action的值产生一个新的对象返回,注意reducer必须是纯函数,也就是说函数的返回结果必须完全由参数state和action决定,而且不产生任何副作用,也不能修改参数state和action对象。

3. Redux使用教程

例子在src目录下,与上节相同的例子加减组件,用Redux改写。

通过三张图了解Redux中的重要概念
先用因为react-redux帮我们省去了很多代码,不利于理解,所以先从redux开始

给出概念图
)

3.1 Action

Action是一个对象,用来代表所有会引起状态(state)变化的行为

action.js如下所示。

// ActionTypes.js
export const INCREMENT = 'increment'

export const DECREMENT = 'decrement'

// Action.js
import * as ActionTypes from './ActionTypes'

export const increment = (counterCaption) => {
    return {
        type: ActionTypes.INCREMENT,
        counterCaption: counterCaption
    }
}

export const decrement = (counterCaption) => {
    return {
        type: ActionTypes.DECREMENT,
        counterCaption: counterCaption
    }
}

3.2 Store

Store是Redux中数据的统一存储,维护着state的所有内容

import { createStore } from 'redux'
import reducer from './Reducer.js'

const initValue = {
    'First': 0,
    'Second': 10,
    'Third': 20
}

const store = createStore(reducer, initValue)

export default store

3.3 Reducer

Reducer决定着如何更新state

``(previousState, action) => newState```

该函数接收两个参数,一个旧的状态previousState和一个Action对象
然后返回一个新的状态newState,去重新渲染View

3.4 View

  1. 初始化状态
    在counter组件中,不在由自己决定状态,而是去store中获取状态
class Counter extends Component {
    constructor(props) {
        super(props)
        this.state = this.getOwnState()
        //...
    }

    getOwnState() {
        const { caption } = this.props
        return {
            value: store.getState()[caption]
        }
    }
}
  1. 监听状态是否发生改变
    肯定要监听组件的状态是否更新, 这里用到了发布订阅模式
import store from '../Store'

//...
componentDidMount() {
   // 通过store.subscribe()监听组件变化,只要组件的状态变化,就会调用onChange方法
   store.subscribe(this.onChange)
}

componentWillUnmount() {
   // 组件删除后,注销监听
   store.unsubscribe(this.onChange)
}

onChange() {
  const newState = this.getOwnState()
  this.setState(newState)
}
  1. 组件更新的时候,想改变状态唯一的办法是派发action
onClickIncrementButton() {
  const { caption } = this.props
  store.dispatch(Actions.increment(caption))
}

onClickDecrementButton() {
  const { caption } = this.props
  store.dispatch(Actions.decrement(caption))
}

大功告成。 看似复杂了很多,增加了很多约束,其实对开发项目有好处,利于提高软件质量

注意一个地方,我们在每个组件里都需要引入store,这样才能更新变化。
但这样做很麻烦,那有啥好的办法呢? 后面会讲到使用Context组件

ps: 其实Redux的核心功能实现并不难,自己实现了一下核心的功能,导入环境能正常使用

// 发布订阅模式
function createStore(reducer, initState) {
    let state = initState
    let listeners = []

    function subscribe(listener) {
        listeners.push(listener)
    }

    function dispatch(action) {
        // 按照 reducer 修改 state
        state = reducer(state, action)
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i]
            listener()
        }
    }

    function getState() {
        return state
    }

    return {
        subscribe,
        dispatch,
        getState,
    }
}

export default createStore