dva系列1 - 有狀態的UI組件主要講述了有狀態的UI組件出現的背景和簡單用法。單純的UI組件雖然也能勝任一些頁面,但是把一些數據認證為state緩存到組件中,數據的變化依賴邏輯的驅動,這樣邏輯和UI組件還是無法徹底分離,依然會在組件中神出鬼沒,並沒有達到我們的目標。我們需要純凈的UI組件,除了渲染邏輯,不再雜糅其他。這樣我們就要想辦法把與渲染無關的邏輯抽離出來,形成獨立的層去管理。

丟掉有狀態的能力,專註做UI渲染

state的變化會依賴邏輯驅動,有污染組件純凈性的風險。那我們就把state統一管理,讓所有組件降級為 無狀態組件,僅僅依賴props渲染。這樣UI層面就不需關心渲染無關的邏輯,專註做UI渲染。舉個無狀態組件的例子:

function StatelessComponent(props){ function handleClick() { props.dispatch({ type: props.isCreate ? app/create : app/update }); } return <div onClick={handleClick}>${props.name}</div>}

分析下上面的例子,可以看出:

1、組件渲染僅僅依賴props數據源;

2、組件僅關心渲染邏輯,如props.isCreate;3、組件重新渲染依賴props的變化;

數據邏輯哪兒去了?

數據邏輯是web應用不可或缺的存在,不然就是一堆靜態頁面,沒有什麼用了。把這些東西從組件中剝離出來,該由誰接盤啊?是時候介紹下我們的這位幕後英雄了——redux,剛有講到邏輯需要接盤俠,redux就是沖這個而來。先看下它具備什麼能力吧。在應用中,它僅做三件事情:

  • 所有的 state 都以一個對象樹的形式儲存在一個單一的 store 中。
  • 惟一改變 state 的辦法是觸發 action,一個描述發生什麼的對象。
  • 如何改變 state 樹,需要交給reducers處理。

舉個例子直觀一些:

import { createStore } from redux;// actionsconst INCREMENT = INCREMENT;function increment() { return { type: INCREMENT };}const DECREMENT = DECREMENT;function decrement() { return { type: DECREMENT };}// reducerfunction counter(state = 0, action) { switch (action.type) { case INCREMENT: return state + 1; case DECREMENT: return state -1; default: return state; }}let store = createStore(counter);// dispatch actionstore.dispatch(increment()); // +1 => 1store.dispatch(increment()); // +1 => 2store.dispatch(decrement()); // -1 => 1store.dispatch(decrement()); // -1 => 0

redux就是這麼簡單,創建一個全局的state樹,通過dispatch action交付reducer處理,更新state樹。它的職責也很單一,僅僅處理數據和邏輯,全程不關心UI。更難能可貴的是,所有action和reducer都是純函數,易於測試。

與dva的對應關係

{ namespace: users, state: { list: [], total: null, page: null, }, reducers: { save(state, { payload: { data: list, total, page } }) { return { ...state, list, total, page }; }, }, effects: { //... }, subscriptions: { //... }}

12 步 30 分鐘,完成用戶管理的 CURD 應用 (react+dva+antd)這篇文章中有一段model層代碼,其實dva-model層的reducer對應的恰恰是redux的reducer;dva-model層的state是redux的store的子集;而在connect-component組件中dispatch的其實就是action。只不過dva框架把創建store隱藏了,action通過namespace/reducer(effect)-name的方式提供了而無需自己定義。

不過dva-model還做了其他事情,比如優雅地封裝了非同步處理,利用effect控制reducer之間的銜接以保證reducer的純函數性。關於這塊此係列結篇我會詳細剖析。

UI層和邏輯層已ready,它們之前如何聯繫呢?不關聯起來的話,組件UI無法感知數據變化,也就無法重現渲染,下一篇我會繼續說關聯它們的技術—— react-redux,敬請期待~

推薦閱讀:

相關文章