Ant Design Pro 腳手架+umiJS 實踐總結
一、簡介
1、Ant Design Pro
Ant Design Pro是一款搭建中後臺管理控制檯的腳手架 ,基於React,dva.js,Ant Design
(1)其中dva主要是控制資料流向,是純粹的資料流,用作狀態管理
使用React技術棧管理大型複雜的應用往往要使用Redux來管理應用的狀態,然而隨著深度使用,Redux也暴露出了一些問題。dva 是一種改良Redux的架構方案,是基於現有應用架構 (redux + react-router + redux-saga 等)的一層輕量封裝,簡化了redux和redux-saga使用上的諸多繁瑣操作。
(2)ant design是一個基於react打造的一個服務於企業級產品的UI框架。
2、umiJS是一個控制路由
以路由為基礎,用來控制路由
二、實踐分析
1、使用Ant Design pro腳手架官網來搭建專案,根據官網教程比較容易,
根據官網可知,使用ant design pro生成的專案目錄為:
其中最重要的四個資料夾,services、modles、mock、pages
- sevices:資料介面
- modles:資料處理
- mock:模擬資料
- pages:頁面
pages觸發modles中的方法來處理資料,若為非同步操作在modles中需要呼叫services中的資料介面方法,在後臺未寫完時可以通過mock中的模擬資料來除錯
具體來說,也即是使用dva時,資料流向或者說觸發流程為:在pages中的jsx檔案中通過dispatch觸發models中的js檔案中的effects或者reducers中的方法,其中effects中的方法是非同步操作,通過yield call(呼叫介面函式方法名)呼叫從services中js檔案引入的定義好的呼叫介面方法,然後通過yield put({type: 'reduceres中的方法'});來觸發 reducers中的方法來修改state。
資料流向圖如下:
資料的改變發生通常是通過:
- 使用者互動行為(使用者點選按鈕等)
- 瀏覽器行為(如路由跳轉等)觸發的
當此類行為會改變資料的時候可以通過 dispatch 發起一個 action,如果是同步行為會直接通過 Reducers 改變 State ,如果是非同步行為(副作用)會先觸發 Effects 然後流向 Reducers 最終改變 State 。
簡單的例項如下:
1、welcome.jsx檔案
import React from 'react'; import { Form, Input, Button, InputNumber } from 'antd'; import { connect } from 'dva'; //將form注入到props中 @Form.create() //將models中的狀態state繫結到props中,解構出myInfo,以data命名繫結到props上 @connect(({lhj:{myInfo}})=>({ //箭頭函式返回一個物件,必須在物件外面加上一個括號 myInfo })) class Welcome extends React.Component{ handleSubmit = e=>{ const { form, dispatch } = this.props; e.preventDefault(); //校驗輸入域的值 form.validateFields((err,values) =>{ if(!err){ console.log(values); //驗證成功 傳入物件{type: 'lhj/check',payload: {...values,}},呼叫lhj中的check函式, dispatch({ type: 'lhj/check', payload: { ...values, } }); } }) //console.log('submit',form.getFieldValue('username')); } handleReset = ()=>{ this.props.form.resetFields(); } render(){ const { getFieldDecorator } = this.props.form; return ( <div> <Form onSubmit={this.handleSubmit} layout="inline"> <Form.Item label="姓名"> {getFieldDecorator('username', { rules: [{required: true, message: 'please input your username'}] })(<Input placeholder="username"/>)} </Form.Item> <Form.Item label="年齡"> {getFieldDecorator('age',{ rules: [ // {type: 'number', message: 'this must be a number'}, {required: true, message: 'please input your age'} ] })(<InputNumber placeholder="age"/>)} </Form.Item> <Form.Item> <Button type="primary" htmlType="submit">查詢</Button> </Form.Item> <Form.Item> <Button onClick={this.handleReset}>取消</Button> </Form.Item> </Form> {this.props.myInfo.username}-{this.props.myInfo.age} </div> ); } } export default Welcome;
2、services/lhj.js檔案
import request from '@/utils/request'; export async function lhjCheck(params){ console.log(params,'services') return request('/api/lhj', { params }); }
3、models/lhj檔案
import {lhjCheck} from '@/services/lhj'; const lhjModel = { namespace: 'lhj', state: { myInfo: { username: '', age: 0, } }, effects: { *check({ payload },{ call, put }){ // console.log(payload,'lhj/check'); const res = yield call(lhjCheck, payload); // console.log(res,'res');//res為從mock中返回的虛擬資料 yield put({ type: 'checkInfo', payload: { myInfo: res }, }) }, }, reducers: { checkInfo(state, { payload }){ console.log(state,payload,'checkInfo'); return { ...state, ...payload,//同名的會覆蓋掉 } }, saveInfo(state){ return { } }, } } export default lhjModel;
4、mock/lhj.js檔案
export default { 'Get /api/lhj': { username: 'lhj', age: 24 }, }
三、幾個知識點總結:
1、connect的作用是將元件和models結合在一起。將models中的state繫結到元件的props中。並提供一些額外的功能,譬如dispatch。通過connect
來繫結繫結model state。意味著Component裡可以拿到Model中定義的資料,Model中也能接收到Component裡dispatch的action。實現了Model和Component的連線。注意@connect必須放在export default class前面
當在元件裡發起action時,直接dispatch就行了(
dispatch({
type: `monthCard/query`,
payload: {}//需要傳遞的資料
})
),dva會幫你自動呼叫effects/reducers。當發起同步action時,type寫成'(namespace)/(reducer)'
dva就幫你呼叫對應名字的reducer直接更新state,當發起非同步action,type就寫成'(namespace)/(effect)'
,dva就幫你呼叫對應名字的effect,然後通過yield put呼叫reducer來實現非同步更新state
3、專案的開發流程一般是從設計model state開始進行抽象資料,完成component後,將元件和model建立關聯,通過dispatch一個action,在reducer中更新資料完成資料同步處理;當需要從伺服器獲取資料時,通過Effects資料非同步處理,然後呼叫Reducer更新全域性state。是一個單向的資料流動過程。