Redux工做流及工程化編碼指南

1、什麼是Redux?

Redux 是 JavaScript 狀態容器, 提供可預測化的狀態管理。它專門爲React.js這門框架設計,但並非只能用於react,能夠用於任何界面庫。react

那爲何React.js須要這個狀態容器管理呢?chrome

首先明確React是什麼,根據官方的定義,React僅僅是一個視圖層的框架,解決的是數據與模板的渲染問題,可是並無提供數據的狀態管理方案,這在大型項目中是一個很是大的痛點。好比說:redux

凡是複雜一些的應用都會有這樣組件樹的結構,那麼非父子組件如何傳遞數據呢?好比標記上藍色的組件與右下角的組件進行數據傳遞,若是僅僅用react組件的父子傳值方法,那麼須要先傳遞給父組件,而後由父組件傳給上一級的父組件,而後再向下面的子組件傳遞......明明只是兩個組件的交互,竟然要 用如此複雜的操做,是否是讓人很是沮喪呢?若是項目稍微複雜,即便能夠開發,但也變得不可維護。所以Redux應運而生。讓Redux統一管理數據,任何組件對數據的操做,都交給redux管理,這樣就大大提升了開發和維護的效率。

2、Redux設計原則

一、單一數據源

使用redux的程序,全部的state都存儲在一個單一的數據源store內部,相似一個巨大的對象樹。框架

二、state只讀

state是隻讀的,外部能改變state的惟一方式是經過觸發action來修改異步

三、使用純函數進行修改

爲了描述action如何改變state,須要編寫一些具體的邏輯,這些邏輯寫在reducer中。而reducer就是一些純函數。函數

純函數:有固定的參數輸入且有固定的return輸出,不會存在異步的操做,同時在這個過程當中不會修改參數的值。ui

3、Redux工做流

也許第一次看不是很明白,沒有關係,能夠用圖書館借書的例子作一個類比:

一圖勝千言,其實redux的工做流程也是很是簡單的。

4、使用redux

// src/store/index.js
import { createStore } from 'redux';
import reducer from './reducer';
//經過createStore建立一個store,把reducer做爲參數傳入
const store = createStore(
  reducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()//chrome中激活redux devtools插件
);

export default store;
複製代碼
// src/store/reduce.js
const defaultState = {
  inputValue: '',
  list: []
}
export default (state = defaultState, action) => {
  if(action.type === 'add_item') {
    const newState = JSON.parse(JSON.stringify(state))
    newState.list.push(newState.inputValue)
    newState.inputValue = ''
    return newState
  }
  return state;
}
複製代碼
// App.js
import React, { Component } from 'react'
import store from './store/index.js'

class App extends Component {
  constructor(props) {
    super(props);
    //從redux拿到state
    this.state = store.getState()
    //store須要經過一個方法給組件傳遞newState,並將這個方法傳入subscribe函數的參數裏面
    this.handleStoreChange = this.handleStoreChange.bind(this)
    store.subscribe(this.handleStoreChange)
  }
  render() { 
    return ( 
     //渲染部分
    );
  }
  handleStoreChange() {
    //更新組件狀態
    this.setState(store.getState())
  }
}

export default App;
複製代碼
//在響應點擊事件的函數中
  handleItemClick(e) {
    const action = {
        type: 'add_item',
        value: e.target.value
    }
    //由store進行action的分發
    store.dispatch(action)
  }
複製代碼

5、更科學地編寫Action

仔細想一想,其實上面編寫響應函數裏面的action部分實際上是有問題,由於當咱們輸入字符串的時候,一不當心輸錯了一個字母,沒法進行狀態的變化,但這個時候reducer識別不了對應的type,也不會報錯。這個時候可能調試會浪費很是多的時間。this

這時候就須要編寫更加規範的action來防止這種事故。spa

// src/store/actionTypes.js
export const ADD_ITEM = 'add_item'

// src/store/actionCreators.js
import { ADD_ITEM } from "./actionTypes";
export const getAddItemAction = (e) => ({
  type: ADD_ITEM
  value: e.target.value
})
// src/store/reducer.js
import { ADD_ITEM } from './actionTypes'

const defaultState = {
  inputValue: '',
  list: []
}
export default (state = defaultState, action) => {
  //這裏改爲ADD_ITEM
  if(action.type === ADD_ITEM) {
    const newState = JSON.parse(JSON.stringify(state))
    newState.list.push(newState.inputValue)
    newState.inputValue = ''
    return newState
  }
  return state;
}
複製代碼

而後,在App.js中,插件

//首先引入Action
import { getAddItemAction } from './store/actionCreators'
//修改響應函數
handleItemClick(e) {
    const action = getAddItemAction(e)
    store.dispatch(action)
}
複製代碼

這樣的編寫方式雖然引入了actionTypes和actionCreators,操做更加 麻煩,可是更能應對大型複雜項目的action管理,實際上提升了開發維護的效率。

這是對redux初步的小結,但願對你們有所幫助。

相關文章
相關標籤/搜索