用JS打造一款记账App——Redux架构设计

2017-04-06  本文已影响279人  Asir王智圣

上一篇我们学习了构建一个react项目以及配置webpack并运行项目,这篇我们在引入redux之前学习它的运行机制及设计思路。

Redux的架构思想

1. state和store 的概念

state是React中定义的应用状态,本质是一个数据集的普通对象,例如

/** 应用初始state **/
{
    status: 0,
    todos: []
}

store是应用状态state的管理者,包含四个函数:

getState() #获取整个state
dispatch(action) #触发state改变的唯一途径
subscribe(listener) #可以理解为DOM中的addEventListener
replayceReducer(nextReducer) #一般在Webpack按需加载的时候用

二者的关系 state = store.getState()

Redux规定:一个应用只应有一个单一的store,其管理着唯一的应用状态state且不能直接被修改,若要改变state,必须执行dispatch一个action,这是修改应用状态的唯一方法。

现在您只需要记住action只是一个包含type属性的普通对象即可
例如{type:'INCREMENT'}

我们知道了state是通过store.getState()获取的,那么store是怎么来的呢?那就需要用到了Redux定义的createStore方法了。

import { createStore } from 'redux'
...
//store是将reducer传入生成的
const store = createStore(reducer, initialState) 

现在您只需要记住reducer是一个函数,负责更新并返回一个新的state,而initialState主要用于前后端同构的数据同步(详情请关注React服务端渲染)

2. reducer

这里我们又要用到Redux中定义的另外一个方法combineReducers。

import { combineReducers } from 'redux'
...
const rootReducer = combineReducers({
  captchaData,
  loginState,
  status,
  userInfo
})

export default rootReducer

具体工作原理是dispatch执行action之后,reducer负责根据action的type属性重新将对应action的payload值赋给nextState

3.Action

上面我们提到了action实质的包含type属性的普通对象,这个type是实现用户行为的关键。例如我们增加一个支出分类

{
    type: 'ADD_CATEGORY',
    payload: {
        id:1,
        content:'交通'
    }
}

当然,action可以根据具体的业务来自由设定,唯一的必要属性就是type,甚至我们可以写一个只包含type属性的action

下面的action都是合法的

{
    type: 'ADD_CATEGORY',
    id:1,
    content:'交通'
}

{
    tyep: 'ADD_CATEGORY',
    aabbcc: {
        id: 1,
        content: '交通'
    }
}
{
    type: 'ADD_CATEGORY'
}

虽然没有约束,但最好还是遵循规范

这里有一个思考问题,action难道就只是包含type等一些属性的对象吗?这里留一个悬念,后面我在具体用Redux的过程中再讲。

Redux优缺点

Action Creator => action => store.dispatch(action) => reducer(state, action) => 原state state = nextState

优点:清晰的数据流向,让我们处理复杂的业务逻辑,可以更加方便的梳理业务线,action只负责执行逻辑操作和数据获取,reducer只负责返回数据集,然后connect给react中的组件使用,让react只关心交互界面的逻辑,无需关心数据逻辑。
另外我们使用redux还有如下好处

使用Redux我们必须遵循Redux的守则

缺点:由于必须遵守Redux的守则,即使很简单的业务逻辑,我们也必须有store,reducer,action.type。这样给人的感觉就是杀鸡用牛刀,所以对于简单的业务逻辑,我们无需引用Redux库。

最后,Redux真正的灵魂在于其设计思想,很多时候并不一定需要引用Redux库本身,但可以尝试使用redux的思想。

import React, { Component } from 'react'

class Counter extends Component {
  state = { value: 0 }
  
  increment = () => {
    this.setState(prevState => ({
      value: prevState.value + 1
    }))
  }

  decrement = () => {
    this.setState(prevState => ({
      value: prevState.value - 1
    }))
  }
  
  render() {
    return (
      <div>
        {this.state.value}
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
      </div>
    )
  }

使用redux,我们可能会有禁用Local State的习惯,其实Local State有时候恰恰是用最简单的方法帮我们解决问题。我们对上面代码用redux思想进行改造

import React, { Component } from 'react'

const counter = (state = { value:0 }, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { value: state.value + 1}
        case 'DECREMENT':
            return { value: state.value - 1}
        default:
            return state
    }
}

class Counter extends Component {
    state = counter(undefined, {})
    
    dispatch(action) {
        this.setState(prevState => counter(prevState, action))
    }
    
    increment = () => {
        this.dispatch({type: 'INCREMENT'})
    }
    
    decrement = () => {
        this.dispatch({type: 'DECREMENT'})
    }
    
    render() {
      return (
         <div>
         {this.state.value}
            <button onClick={this.increment}>+</button>
            <button onClick={this.decrement}>-</button>
         </div>
    )
  }
}

总结

这一篇我们理解了Redux的几个概念以及设计思想,下一篇我们要在项目中引用Redux库并学习怎么使用它。

上一篇下一篇

猜你喜欢

热点阅读