Redux 入門 -- 基礎用法

阿希發表於2018-04-16

本文目標:希望通過買水果的例子,和大家探討下 redux 的基礎用法,能快速入門 redux

例子:買水果

一天,程式設計師阿大(化名)想要去買水果吃,發現小區周圍居然沒有水果店,於是就打算自己開一個水果店賺點小錢。

阿大分析了一下水果店的營業模式。其實就是處理每一位顧客的需求,然後記賬看看每天的盈虧。那麼抽象成程式就是監聽顧客的行為,並把每個行為的結果都記在賬上,這正好是 redux 所擅長的。阿大胸有成竹,說著就開始寫了起來:

首先模擬顧客的購買行為:

const action = {
  type: 'BUY_APPLE', // 買蘋果
  payload: {
    count: 2 // 買 2 斤
  }
}
複製程式碼

那不同的顧客要的斤數可能不同,於是他寫了下面這個方法:

/**
 * 只要知道斤數就可以快速生成顧客的各種需求
 * @param {number} num 顧客要買的斤數 
 */
function buyApple(num) {
  return {
    type: 'BUY_APPLE',
    payload: {
      count: num
    }
  }
}
複製程式碼

然後是賬本的結構,記錄每天賣了多少斤:

// 被託管的資料 state
// 賬本,今天已賣的蘋果:0 斤;為了簡便,就只舉一個例子,事實上還有很多其他水果,大家自行腦補
const state = { apple: 0 }; 
複製程式碼

好了,現在顧客需求,賬本都有了,那誰來記賬呢?所以阿大請了一個收銀員負責記賬,並告訴他這麼記賬:

/**
 * 監聽函式 listener
 * 收銀員只要知道顧客的需求就能正確的操作賬本
 * @param {object} state 賬本
 * @param {object} action 顧客的需求
 */
function reducer(state, action) {

  // 註冊 ‘買蘋果’ 事件
  // 如果有人買了蘋果,加上顧客買的斤數,更新賬本
  if (action.type === 'BUY_APPLE') {
    return Object.assign({}, state, {
      apple: state.apple + action.payload.count
    });
  }

  // 沒註冊的事件不作處理
  // 買我們們店裡沒有的東西,不更新賬本,原樣返回
  return state;
}
複製程式碼

好,萬事俱備,可以正式的監聽顧客的購買需求並更新賬本了:

const { createStore } = require('redux');

// 建立水果店需要收銀員(監聽函式 listener)和賬本(被託管的資料)
const store = createStore(reducer, state);
複製程式碼

不僅如此,redux 還提供了一個功能,每服務一個顧客,都可以額外做一些事情,於是阿大就想看看每筆交易之後的賬本:

// store.getState() 可以獲取最新的 state
store.subscribe(() => console.log(JSON.stringify(store.getState())));
複製程式碼

好了,顧客開始來買水果了:

// 觸發使用者購買水果的事件
// 銷售員開始銷售
store.dispatch(buyApple(3)); // {"apple":3}
store.dispatch(buyApple(4)); // {"apple":7}
複製程式碼

店鋪穩定的運營了下去,阿大心裡美滋滋~

講解

上面的例子涉及到了 redux 的幾個概念:actionaction creatorstatestore

不過在此之前要先說 redux 特別講究也是特別重要的 3 點:

  1. 只能有唯一的 store 物件儲存整個應用的 state
  2. state 是隻讀的,只能通過 dispatch(action) 的方式來改變 state
  3. reducer 必須是純函式

action

action 是行為資訊的抽象,物件型別,它描述發生了什麼。這個物件必須有一個 type 屬性,對於物件裡面的其他內容,redux 不做限制。但是推薦符合 Flux Standard Action 規範:

{
  type: 'ACTION_TYPE',
  payload, // action 攜帶的資料
}
複製程式碼

action creator

action creator 顧名思義就是用來建立 action 的,action creator 只簡單的返回 action。

function createAction(num) {
  return {
    type: 'ACTION_TYPE',
    payload,
  }
}
複製程式碼

state

state 是被託管的資料,也就是每次觸發監聽事件,我們要操作的資料。

reducer

reducer 是用來控制 state 改變的函式。action 描述了發生了什麼,但是並不會知道相應的 state 該怎麼改變。對於不同的 action,相應的 state 變化是用 reducer 來描述的。

reducer 接受兩個函式,第一個是 state,第二個是 action,並返回計算之後新的 state。reducer 必須是一個純函式,對於相同的輸入 state 和 action,一定會返回相同的新的 state。

nextState = reducer(prevState, action);
複製程式碼

因為 reducer 是純函式,所以原來的 prevState 並不會改變,新的 nextState 是一個最新的快照。

store

store 是把上面三個元素合起來的一個大物件:

{
  createStore,
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose,
  __DO_NOT_USE__ActionTypes
}
複製程式碼

它負責:

  • 託管應用的 state
  • 允許通過 store.getState() 方法訪問到託管的 state
  • 允許通過 store.dispatch() 方法來觸發 action 更新 state
  • 允許通過 store.subscribe() 註冊監聽函式監聽每一次的 action 觸發
  • 允許登出通過 store.subscribe() 方法註冊的監聽函式
// 註冊
const unsubscribe = store.subscribe(() => { /** do something */});

// 登出
unsubscribe();
複製程式碼

圖解

Redux 入門 -- 基礎用法

程式碼地址:Redux 入門 -- 基礎用法,直接控制檯執行 node ./demo1/index.js 檢視效果

上一篇:Redux 是什麼

下一篇:Redux 入門 -- 拆分 reducer