Redux學習筆記

Facebook:MVC不適合大規模應用,改用Flux Redux中文文檔 經過漫畫學習Reduxhtml

Redux簡介

使用Redux緣由git

隨着 JavaScript 單頁應用開發日趨複雜,JavaScript 須要管理比任什麼時候候都要多的 state (狀態),很難維護。甚至state 在何時,因爲什麼緣由,如何變化已然不受控制。 ,Redux 試圖讓 state 的變化變得可預測。github

Redux和Flux很是類似。數據庫

三大原則redux

1.單一數據源api

整個應用的 state 被儲存在一棵 object tree 中,而且這個 object tree 只存在於惟一一個 store 中。bash

2.State 是隻讀的mvc

唯一改變 state 的方法就是觸發 action,action 是一個用於描述已發生事件的普通對象。app

3.使用純函數來執行修改dom

爲了描述 action 如何改變 state tree ,你須要編寫 reducers

Redux基礎

Action

Action 是把數據從應用傳到 store 的有效載荷。它是 store 數據的惟一來源。

通常來講你會經過store.dispatch()  將 action 傳到 store。

Action 本質上是 JavaScript 普通對象。 action 內必須使用一個字符串類型的 type字段來表示將要執行的動做。其他可自定義,能夠參考 Flux 標準 Action 原則上,儘可能減小在 action 中傳遞的數據

一般 type會被定義成字符串常量。

const ADD_TODO = 'ADD_TODO'
複製代碼
{
  type: ADD_TODO,
  text: 'Build my first Redux app'
}
複製代碼

當應用規模愈來愈大時,建議使用單獨的模塊或文件來存放 action。

import { ADD_TODO, REMOVE_TODO } from '../actionTypes'
複製代碼

Action建立函數

Action 建立函數 就是生成 action 的方法。

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}
複製代碼

下面展現一下一個anction.js的例子

/*
 * action 類型
 */

export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'

/*
 * 其它的常量
 */

export const VisibilityFilters = {
    SHOW_ALL: 'SHOW_ALL',
    SHOW_COMPLETED: 'SHOW_COMPLETED',
    SHOW_ACTIVE: 'SHOW_ACTIVE'
}

/*
 * action 建立函數
 */

export function addTodo(text) {
    return { type: ADD_TODO, text }
}

export function toggleTodo(index) {
    return { type: TOGGLE_TODO, index }
}

export function setVisibilityFilter(filter) {
    return { type: SET_VISIBILITY_FILTER, filter }
}
複製代碼

Reducer

Action 只是描述了有事情發生了這一事實,並無指明應用如何更新 state。而這正是 reducer 要作的事情。

設計 State 結構

Redux 應用中,全部的 state 都被保存在一個單一對象中,建議在寫代碼前先想一下這個對象的結構。

開發複雜的應用時,不可避免會有一些數據相互引用。建議你儘量地把 state 範式化,不存在嵌套。把全部數據放到一個對象裏,每一個數據以 ID 爲主鍵,不一樣實體或列表間經過 ID 相互引用數據。把應用的 state 想像成數據庫。參考 normalizr 文檔

文檔中的例子比較簡單,是以下設計的

{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}
複製代碼

Action 處理

reducer 就是一個純函數,接收舊的 state 和 action,返回新的 state。 之因此稱做 reducer 是由於它將被傳遞給 Array.prototype.reduce(reducer, ?initialValue)  方法。

(previousState, action) => newState
複製代碼

永遠不要在 reducer 裏作這些操做:

  • 修改傳入參數;
  • 執行有反作用的操做,如 API 請求和路由跳轉;
  • 調用非純函數,如 Date.now() 或 Math.random()。

只要傳入參數相同,返回計算獲得的下一個 state 就必定相同。沒有特殊狀況、沒有反作用,沒有 API 請求、沒有變量修改,單純執行計算。

明白了這些以後,就能夠開始編寫 reducer,並讓它來處理以前定義過的 action Redux 首次執行時,state 爲 undefined,此時咱們可藉機設置並返回應用的初始 state。

import { VisibilityFilters } from './actions'

const initialState = {
  visibilityFilter: VisibilityFilters.SHOW_ALL,
  todos: []
};

function todoApp(state, action) {
  if (typeof state === 'undefined') {
    return initialState
  }

  // 這裏暫不處理任何 action,
  // 僅返回傳入的 state。
  return state
}
複製代碼

這裏一個技巧是使用 ES6 參數默認值語法 來精簡代碼。

function todoApp(state = initialState, action) {
  // 這裏暫不處理任何 action,
  // 僅返回傳入的 state。
  return state
}
複製代碼

如今能夠處理 SET_VISIBILITY_FILTER。須要作的只是改變 state 中的 visibilityFilter。

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}
複製代碼

注意:

  1. 不要修改 state。 使用 Object.assign() 新建了一個副本。不能這樣使用 Object.assign(state, { visibilityFilter: action.filter }),由於它會改變第一個參數的值。你必須把第一個參數設置爲空對象。

  2. **在 default 狀況下返回舊的 state。**遇到未知的 action 時,必定要返回舊的 state。

處理多個 action

Paste_Image.png
相關文章
相關標籤/搜索