使用UmiJS和DvaJS完成用户管理系统
前言
對React溫習差不多了,是時候嘗試制作個小項目。目前使用UmiJS + DvaJS來構建項目。
UmiJS是一個可插拔的企業級 react 應用框架,具體可查看官網文檔
DvaJS是dva 首先是一個基于 redux 和 redux-saga 的數據流方案,然后為了簡化開發體驗,dva 還額外內置了 react-router 和 fetch,所以也可以理解為一個輕量級的應用框架。官網地址:https://dvajs.com
創建項目
創建UmiJS項目很簡單,根據文檔的通過腳手架創建項目步驟就行了,這里不多描述。
提示安裝類型:
Select the boilerplate type 選擇 app
Do you want to use typescript? 選擇 No
What functionality do you want to enable? 空格鍵選擇 antd和dva回車確定
antd是螞蟻金服的React UI框架,它的設計非常精美,其官網地址:https://ant.design/index-cn。這里加個UI框架只是為了項目數據展示美觀些。
配置代理
下面插點數據,既然是用戶管理系統就需要一些用戶信息,利用mock制造一些json數據:http://jsonplaceholder.typicode.com/users,由于跨域等問題,還是將這個地址反代自己地址吧。根據UmiJS問題的Proxy配置,需要在項目目錄下的.umirc.js或者config/config.js添加編輯:
"proxy": {"/api": {"target": "http://jsonplaceholder.typicode.com/","changeOrigin": true,"pathRewrite": { "^/api" : "" }} }然后啟動項目yarn start訪問地址:http://localhost:8000/api/users是否成功。
生成路由
編寫路由前有必要先了解下UmiJS路由運行方式:UmiJS 路由,路由就是應用不同的頁面組成的,如果地址欄是/user/則頁面應該是src/pages/user.js。當然你可以手動新建個js/css文件,不過UmiJS提供npx新建路由的方式:
yarn global add npx # 安裝npx模塊npx umi g page user # 新建/user路由然后可以在http://localhost:8000/user訪問了。
構造 model 和 services
如果在src/model和src/services目錄下新建文件名字和src/pages相同,Umi會自動注入同名業務代碼。
可以利用DvaJS中的fetch方式訪問接口獲取數據,然后在src/utils/request.js編寫一層fetch封裝方法:
import fetch from 'dva/fetch';function checkStatus(response) {if (response.status >= 200 && response.status < 300) {return response;}const error = new Error(response.statusText);error.response = response;throw error; }/** * Requests a URL, returning a promise. ** @param {string} url The URL we want to request* @param {object} [options] The options we want to pass to "fetch"* @return {object} An object containing either "data" or "err" */ export default async function request(url, options) {const response = await fetch(url, options);checkStatus(response);const data = await response.json();const ret = {data,headers: {},};if (response.headers.get('x-total-count')) {ret.headers['x-total-count'] = response.headers.get('x-total-count');}return ret; }關于具體的Fetch資料可以到網上查閱。
然后建立請求接口的文件,在新建src/services/user.js:
import { PAGE_SIZE } from '../constants' import request from '@/utils/request'export function queryUserList({ page = 1 }) {return request(`/api/users?_page=${page}&_limit=${PAGE_SIZE}`); }這里的請求是_page是當前頁碼,_limit是當前頁碼數據數量。
在src/constants.js編寫:
export const PAGE_SIZE = 5;當然可以在請求參數里寫死。
請求服務業務寫完了,下面寫models層業務,該業務主要是處理數據和邏輯,DvaJS通過model的概念把一個領域的模型管理起來,包含同步更新state的reducers,處理異步邏輯的effects,訂閱數據源的 subscriptions:
新建src/models/users.js
import { queryUserList } from '@/services/users';export default {namespace: 'users',state: {list: [],total: null,page: null,},reducers: {// 保存數據save(state, { payload: { data: list, total, page } }) {// 復制數組,將list, total, page內容復制到statereturn { ...state, list, total, page };},},effects: {// 訪問接口獲取數據 并且保存數據*fetchUserList({ payload: { page = 1 } }, { call, put }) {const { data, headers } = yield call(queryUserList, { page });yield put({type: 'save',payload: {data,total: parseInt(headers['x-total-count'], 10) ,page: parseInt(page, 10)}});},},subscriptions: {// https://github.com/dvajs/dva/issues/174setup({ dispatch, history }) {return history.listen(({ pathname, query }) => {// 進入'/users'地址觸發fetchUserListif (pathname === '/users') {dispatch({ type: 'fetchUserList', payload: query });}});},}, };看著有點多,但里面內容基本都是固定規范,詳細的說明可以去DvaJS官網文檔 Model查閱:
- namespace:表示在全局state上的唯一名稱
- state:表示初始值
- reducers:用于處理同步操作,唯一可以修改state的地方
- effects:以key/value格式定義effect。用于處理異步操作和業務邏輯,不直接修改state
- subscriptions:用于訂閱一個數據源,然后根據需要 dispatch 相應的 action
構建 UI
修改src/pages/users.js:
import { connect } from 'dva'; import { Table, Pagination, Popconfirm } from 'antd'; import styles from './users.css'; import { PAGE_SIZE } from '../constants';/** * 用戶列表管理 * @param dispatch DvaJS dispatch函數 用于觸發action 的函數 詳解:https://dvajs.com/guide/concepts.html#dispatch-%E5%87%BD%E6%95%B0 * @param dataSource 用戶列表信息 * @param total 總數據數量 * @param loading 加載狀態 * @param current 當前頁碼 * @returns {*} * @constructor */ function Users({ dispatch, list: dataSource, loading, total, page: current }) {function deleteHandler(id) {console.warn(`TODO: ${id}`);}/*** 頁碼改變的回調* @param page 改變后的頁碼* @param pageSize 每頁條數*/function onChangeUserPagination(page, pageSize) {dispatch({type: 'users/fetchUserList',payload: {page: page}, // 需要傳遞的信息});}const columns = [{title: '用戶名',dataIndex: 'name',key: 'name',},{title: '電子郵件',dataIndex: 'email',key: 'email',},{title: '個人網站',dataIndex: 'website',key: 'website',},{title: '操作',key: 'operation',render: (text, { id }) => (<span className={styles.operation}><Button>編輯</Button><Popconfirm title="Confirm to delete?" onConfirm={deleteHandler.bind(null, id)}><Button>刪除</Button></Popconfirm></span>),},];return (<div className={styles.normal}><div><Tableloading={loading}columns={columns}dataSource={dataSource}rowKey={record => record.id}pagination={false}/><PaginationclassName="ant-table-pagination"total={total} // 數據總數current={current} // 當前頁數pageSize={PAGE_SIZE} // 每頁條數onChange={onChangeUserPagination}/></div></div>); }function mapStateToProps(state) {const { list, total, page } = state.users;return {list,total,page,loading: state.loading.models.users,}; }export default connect(mapStateToProps)(Users);這個頁面用到了antd的表格和分頁倆個組件,渲染組件是標準的React函數組件,接受帶數據的props對象。
上面是進入頁面獲取數據,如果是主動性獲取數據也很簡單:先注釋src/moudel/users.js中的subscriptions訂閱模式模塊,然后在src/pages/users.js添加按鈕:
function getUserListData() {dispatch({type: 'users/fetchUserList',payload: {}, // 需要傳遞的信息});} ...return (<div className={styles.normal}><div><Button type="primary" onClick={getUserListData}>獲取用戶數據</Button><Tableloading={loading}columns={columns}dataSource={dataSource}rowKey={record => record.id}pagination={false}/> ...就這樣一個簡單的頁面構建完成。所以完整的功能頁面就不在這篇文章詳細的編寫了,整個業務邏輯和上述過程差不多。
雖然之前做過不少Vue.js單應用頁面開發,對比React應用開發,雖然是吃力了些,也麻煩了些,但很對地方寫法比Vue.js開發優雅了許多。
參考資料
dva.js 知識導圖
Umi入門
總結
以上是生活随笔為你收集整理的使用UmiJS和DvaJS完成用户管理系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 激战和ErgoDex DX1
- 下一篇: 当前安全设置不允许下载该文件的原因以及图