1. 程式人生 > >基於react 16 dva 2 的後臺管理UI

基於react 16 dva 2 的後臺管理UI

dva-boot-admin 是一個用React開發的一個企業級中後臺管理UI,包含常用的業務,元件,及資料流轉方案,前後端分離的開發方式,按業務劃分的目錄結構,可以大大提高我們的開發效率

下面是整體的介紹,感興趣的同學可以去官網詳加了解。
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

功能

  • 封裝了dva框架的資料流轉,簡單的請求可以不用在model和service中定義
  • 封裝了資料模模擬,可以獨立於後臺開發前臺功能
  • 封裝了分頁請求,簡化並規範了分頁邏輯
  • 封裝了fetch請求,適應與後臺多種互動請求, body引數 parameter引數 path引數,動態請求頭,請求前後攔截
  • 擴充套件了antd寫了許多實用的UI,通過一個配置生成即可生成,後臺CRUD三件套
  • 按業務模組劃分的目錄結構,儘量做到最小耦合
  • 一些常用的小部件用法
  • 許多精心設計的頁面及互動場景
  • 全域性異常處理,全域性請求攔截,公共配置提取

目錄結構

.
├── public                   # 不參與編譯的資原始檔
├── src                      # 主程式目錄
│   ├── index.js             # 程式啟動和渲染入口檔案
│   ├── components           # 全域性公共元件
│   ├── layouts              # 頁面結構元件
│   │   ├── BasicLayout      # 基本佈局
│ │ └── OtherLayout # 佈局元件根據具體功能調整,在路由配置中引用 │ ├── routes # 動態路由目錄(每個功能一個資料夾的MVC結構) │ │ ├── index.js # 路由配置檔案 │ │ ├── Home # 功能模組 │ │ │ ├── index.js # 路由配置檔案 │ │ │ ├── assets # 單獨屬於這個模組的靜態資原始檔 │ │ │ ├── components # 頁面元件
│ │ │ ├── model # dva model │ │ │ ├── service # dva service │ │ │ └── routes ** # 子路由(目錄結構與父級相同) │ │ └── Login # 功能模組 │ │ ├── index.js # 路由配置檔案 │ │ ├── assets # 單獨屬於這個模組的靜態資原始檔 │ │ ├── components # 頁面元件 │ │ ├── model # dva model │ │ ├── service # dva service │ │ └── routes ** # 子路由(目錄結構與父級相同) │ ├── utils # 工具類 │ └── assets # 資原始檔 │ ├── fonts # 字型 & 字型圖示 │ ├── images # 圖片 │ └── styles # 全域性樣式

常用方法

modelEnhance

modelEnhance是對dva model層的簡單包裝函式,有時候我們只是想要簡單的fetch一下,從服務端獲取資料進行展示,之前可能要專門在model中寫一些effects和reducers,在service中定義請求函式,如果用modelEnhance包裝一下的話可以簡寫成下面的形式

// src/routes/UserInfo/model/index.js

import modelEnhance from '@/utils/modelEnhance';

// 就是普通的dva model傳入modelEnhance即可,不用定義其它變數
export default modelEnhance({
  namespace: 'userInfo',
});

// src/routes/UserInfo/components/index.js

// 在元件中直接發出一個型別為`@request`的action,
// 結果會存入userInfo對應的state中,使用的key為`valueField`的值
this.props.dispatch({
  type: 'userInfo/@request',
  payload: {
    url: 'http://httpbin.org/get',
    valueField: 'httpbin',
    method: 'GET'
  }
});

// 同時請求兩個
this.props.dispatch({
  type: 'userInfo/@request',
  payload: [{
    url: 'http://httpbin.org/get',
    valueField: 'httpbin',
    method: 'GET'
  }, {
    url: 'http://httpbin.org/post',
    valueField: 'httpbin'
  }]
});

// 結合分頁助手使用,查詢第1頁10條資料
this.props.dispatch({
  type: 'userInfo/@request',
  payload: {
    valueField: 'pageData',
    url: '/api/userInfo/getList',
    pageInfo: pageData.startPage(1, 10),
  }
});

exception

全域性異常處理,我們可以在src/config.js的exceptiion中處理通用異常,這裡共實就是dva的onError方法的入口,我們一般處理如登入超時,使用者沒有許可權,或另種請求異常等,建議大家不同的異常可以單獨包裝成一個異常類進行分類處理,這樣更容易維護以及除錯。

config

工程的配置檔案

fetch mock

模擬服務端響應資料,常常用在前後端分離的專案中,我們在開發新功能的時候,前後端是不同步的,這時我們就會建立一些資料原型,協商好後這時後端就可以開始開發,而我們可以繼續使用模擬資料,只有當後端完成這個介面並測試通過後,二者才會被整合。這之後如果後端因為某些原因服務不可用時,我們也會很方便的切換回模擬資料,這樣不會因為後端的問題而影響後續的開發。

要新建一些模擬資料只要在__mocks__資料夾中,建立一個檔案,並在資料夾中的index.js中進行宣告,一些例子可以直接在資料夾下面找到。

所有的模擬資料是在開發環境中執行的,當您打包成生產環境的包時,會自動遮蔽所有模擬資料介面。

// 例子: /src/__mocks__/userInfo.js
/**
 * 模擬請求資料
 * @param {FetchMock} fetchMock 當現有條件不滿足時,可以使用fetchMock來進行擴充套件
 * @param {number} delay 增加延遲時間 ms
 * @param {function} mock 使用mock生成資料,例如:

   mock({
     'string|1-10': '★' // 生成最少1顆,最多10顆星字元
   })
   // {'string': '★★★★★★'} 
 */
export default ({fetchMock, delay, mock}) => {
  // 如果現有擴充套件不滿足需求,可以直接使用fetchMock方法
  // fetchMock.mock(/httpbin.org\/post/, {/* response */}, {/* options */});

  return {
    // 一般用法
    'GET /api/getUserInfo': {
      name: 'jonn'
    },
    // 省略 method, 模擬真實請求延遲效果
    '/api/getUsers': delay([
      { name: 'jonn' },
      { name: 'weiq' },
    ]),
    // 表格帶分頁
    '/api/userInfo/getList': delay(mock({
      'pageNum|+1': 1,                      // 遞增加1
      'pageSize': 10,
      'size': 10,
      'total': 500,
      'totalPages': 50,
      'list|10': [{
        'name': '@cname',                   // 中文名稱
        'age|1-100': 100,                   // 100以內隨機整數
        'birthday': '@date("yyyy-MM-dd")',  // 日期
        'city': '@city(true)',              // 中國城市
        'phone': /^1[385][1-9]\d{8}/        // 手機號
      }],
    })),
    // 表格帶分頁, 寫成函式形式可以使用請求引數,
    // 更真實的模擬後端資料處理業務
    '/api/userInfo/getList1': (options) => {
      const body = JSON.parse(options.body);
      const pageNum = body.pageNum;
      const idbase = (pageNum - 1) * 10 + 1;
      return toSuccess(mock({
        'pageNum': pageNum,
        'pageSize': 10,
        'size': 10,
        'total': 100,
        'totalPages': 10,
        'list|10': [{
          'id|+1': idbase,
          'name': '@cname',                   // 中文名稱
          'age|1-100': 100,                   // 100以內隨機整數
          'birthday': '@date("yyyy-MM-dd")',  // 日期
          'city': '@city(true)',              // 中國城市
          'phone': /^1[385][1-9]\d{8}/        // 手機號
        }],
      }), 400)
    }
  } 
}

page helper (簡單分頁)

在做後臺系統的時候,做的最多的可能就是對錶格的增、刪、改、查,這時我們的頁面一般是這樣的,上面是對錶格條件的檢索框,中間是我們的資料表格,表格下面是分頁元件,還會有新增,修改時用到表單元件

拿對錶格資料進行檢索這個場景來說,在搜尋框(可能有多個)輸入條件,點選搜尋,檢索到結果(可能非常多),我們會點選下面的分頁元件進行翻頁,翻頁時我們就得帶著之前的檢索條件,我們會在傳送請求前手動合併這些條件,並計算下一頁的頁數等

PageHelper分頁助手就是為了簡化我們的程式碼量的,如使用PageHelper.create()這個方法會為我們自動生成分頁物件

// model.js

state: {
  pageData: PageHelper.create()
}

這時我們可以在元件中使用這個物件很方便的進行分頁,及檢索,並且支援鏈式寫法,所有條件會自動進行合併,如:

// components

const {pageData} = this.props;
// 查詢第1頁,每頁10條,並且name為jonn的資料
pageData.startPage(1, 10).filter({name: 'jonn'}).filter(...).sortBy(...);

// 查詢下一頁,並且會帶著之前的查詢條件
pageData.nextPage();

我們還可以結合modelEnhance來使用分頁,更多用法會在例子中進行說明。

cmn-utils

腳手架使用了cmn-utils做為工具庫,這裡面提供了請求、儲存、事件等許多實用方法

開發&執行

$ git clone https://github.com/LANIF-UI/dva-boot.git
$ cd dva-boot
$ yarn
$ yarn start
// 或使用npm
$ npm install
$ npm start