react-dva學習

dva是一個在redux和redux-saga的基礎上封裝的一個輕型框架,能輔助更好的組織代碼進行開發。同時提供了react-router和fetch,基本上具備了開發web前端應用所需的主要工具,省下開發者自己進行配置安裝的工作。

開始使用dva

首先使用dva-cli快速創建dva應用。

npm install dva-cli -g

使用dva快速創建新的項目框架。

dva new my-new-project

dva會默認使用tnpm, cnpm依賴安裝,由於我現在的tnpm不能使用,只能把tnpm刪掉。

問題:如何配置dva的默認npm源

項目結構

dva-cli會創建如下的初始化項目結構

.
├── .editorconfig
├── .eslintrc
├── .gitignore
├── .roadhogrc.mock.js
├── .webpackrc    // webpack 配置
├── mock
│   └── .gitkeep
├── package.json
├── public
│   └── index.html
└── src
    ├── assets
    │   └── yay.jpg
    ├── components
    │   └── Example.js
    ├── index.css
    ├── index.js
    ├── models
    │   └── example.js    // 數據(狀態)管理中心
    ├── router.js    // 路由
    ├── routes
    │   ├── IndexPage.css
    │   └── IndexPage.js    // 路由中對應的頁面入口
    ├── services
    │   └── example.js
    └── utils
        └── request.js

接下來根據我的個人喜好對項目進行微調 * 加入pages目錄,區別於components,前者用於放置頁面的個性化組件,後者用於放置複用性強的公共組件。然而這種組織一定程度上使得routes的存在沒有太大的意義。

在dva中使用redux
如果決定使用redux的話,需要在src/index.js里加入要用的model

// 3. Model
app.model(require('./models/example1').default);
app.model(require('./models/example2').default);

在dva中使用redux-router
在router.js中將頁面入口組件引入並配置相關的路由

import IndexPage from './routes/IndexPage';
import ManagerPage from './routes/ManagerPage';
import EntryPage from './routes/EntryPage';

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
          <Route path="/user" exact component={IndexPage} />
          <Route path="/manager" exact component={ManagerPage} />
          <Route path="/entry" exact component={EntryPage} />
      </Switch>
    </Router>
  );
}

在model中使用redux-router

import { routerRedux } from 'dva/router';

put(routerRedux.push('/manager'))

routerRedux.push('/manager')

在組件中使用redux-router

import { routerRedux } from 'dva/router';

dispatch(routerRedux.push('/manager'))

接下來就可以愉快的開發了。

dva中的redux

首先,在使用dva開發時,可以將store拆分爲多個model,每個model對應一個namespace,對於複雜的應用,這種組織方式更貼近邏輯,使得問題更爲清晰。對比我之前在vue中將store拆爲state, getters, mutations, actions要更科學一些。後者的查分方式可以成爲“橫向拆分”, 而前者的拆分方式則是一種“縱向拆分”。 這種縱向拆分使得每一個拆分出來的子集都是一個子服務的對應。該自己可以包含自己的state,reducers和effects,可以認爲是一種前端微服務化的思想。

dva對store的構成與vuex相似,都將同步reducers和異步reducers拆分開來,以更好的管理監控異步操作。dva在異步處理上使用了redux-saga,藉助Genarator來實現異步操作。

問題:爲什麼不使用async呢?是歷史問題,還是二者在細節層面存在差別。
generator函數的使用

關於Generator Generator使用*標識函數爲Generator函數 使用yield阻斷異步操作,等到yield後的表達式完成計算得到返回值時,再繼續執行下面的代碼。 關於是否要對同步操作使用yield,我認爲沒有嚴格的限制。但如果其中存在你所關心的中間狀態變量,可以加上yield。這樣就可以在調用next()方法時在返回對象的value屬性中查詢到。

這點與async不同,async返回的是promise,而generator返回的則是狀態對象
redux-saga中異步effects的函數有三個參數

*postFile({ payload }, {call, put}) {
      // handle both create and update
      let res = yield call(fetch, '//api.center/postFile', {
        method: 'post',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      })
      let result = yield res.json()
      if (result.success) {
        yield put({ type: 'getFileList' })
      }
    },
{ payload } = action, 調用dispatch時所傳遞的參數
{call, put}call負責調用異步操作,put則調用其他reducers來完成對state的修改操作

這與vuex不同,vuex中的action可以直接修改state(也可以調用mutations),但直接修改會導致action的邏輯過於複雜,失去了分段調試監控的優勢。

call(異步操作函數,參數1,參數2,…)return 異步函數的返回值(promise或值)
put({type, payload}) 與dispatch參數相同,但type中不需要定義命名空間
reducers的設計
在dva給出的實例代碼中,有一個reducers的定義十分有趣

save(state, action) {
  return { ...state, ...action.payload };
}

這種實現是對所有reducers的本質抽象,即修改state。在實踐簡單應用的開發時,基本上所有的reducers都可以只用這一個save來實現。那是不是無需編寫其他的reducers了呢? 我認爲不是的,對於如下情況,仍需對每一種情況編寫對應的reducers 修改的狀態(state)過多,導致難以通過修改值直接判斷reducer所代表的邏輯是什麼(在哪裏調用,爲什麼調用)。這種情況下建議新定義reducer,對一個state的操作集進行封裝,以便在調試時清楚被調用的reducer對應的業務邏輯是什麼。 需要根據參數進行預計算,最終得到state。這時,建議將一些重要的邏輯運算遷移到reducer中,以方便管理或複用。

開放的webpack配置

.webpackrc使得可以根據個人需求對react進行配置而無需進行eject操作。 (也可以將.webpackrc改爲.webpackrc.json從而使用json格式的配置) 如,我們可以配置babel插件來直接引入如antd或next之類的框架

{
   "extraBabelPlugins": [
    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": true
    }]
  ]
}

如果不想使用css modules功能 (比如next的import配置失敗,只能手動導入css),還可以加入

“disableCSSModules”: true
不過,建議體驗一下css modules的功能

import styles from './style.css';

Hello React!

參考資料 Dva官網:[https://dvajs.com/guide/](https://dvajs.com/guide/)

ES6 Generator:http://es6.ruanyifeng.com/#docs/generator

dva.js入門 https://www.jianshu.com/p/c7b3b9c98d04

antd配置:https://ant.design/docs/react/introduce-cn react eject:https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-eject

redux saga:https://redux-saga-in-chinese.js.org/

發佈了38 篇原創文章 · 獲贊 6 · 訪問量 5006
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章