1. 程式人生 > >Ant Design Pro V5 從伺服器請求選單(typescript版)

Ant Design Pro V5 從伺服器請求選單(typescript版)

## 【前言】 > 找了很多Admin模板,最後還是看中了AntDesignPro(下文簡寫antd pro)這個阿里巴巴開源的Admin框架,長這樣(還行吧,目前挺主流的): 官網地址:[https://pro.ant.design/index-cn](https://pro.ant.design/index-cn) ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806105315496-1289806863.png) 該套模板是使用了React開發框架作為基礎,AntDesign(螞蟻金服開源UI元件庫)作為UI庫,集成了Dva,Umi,Mock等庫,如果不是很瞭解這些內容,門檻還是比較高的。 我們今天需要實現一個需求:將Antd Pro模板中固定寫死的選單換成從伺服器請求選單然後進行渲染 為啥非要自己寫,官網文件不香嗎?----官方文件寫的實在太草了,而且目前沒有typescript方式的文件,需要踩多少坑...不過沒關係,看完這篇坑就都基本填平了 關於Antd Pro第一步,如何建立並執行Antd Pro,可以移步 [https://www.cnblogs.com/7tiny/p/13444963.html](https://www.cnblogs.com/7tiny/p/13444963.html) ## 【瞭解專案中的dva和Umi用法】 antd pro 預設採用了Umi和dva元件,因此想要在基礎上新增功能必須瞭解資料請求和資料流向 在dva中主要分3層,models,services,components,其中models是最重要概念,這裡放的是各種資料,與資料互動的應該都是在這裡。services是請求後臺介面的方法。components是我們編寫的元件。 #### service層 service 層僅僅是封裝了用request請求服務端的api的邏輯,這裡不涉及業務邏輯,比較簡單,例如下面程式碼: ```typescript import request from '@/utils/request'; export interface LoginParamsType { userName: string; password: string; mobile: string; captcha: string; } export function fakeAccountLogin(params: LoginParamsType) { return request('/api/login/account', { method: 'POST', data: params, }); } export async function getFakeCaptcha(mobile: string) { return request(`/api/login/captcha?mobile=${mobile}`); } ``` #### models層 models層是核心業務邏輯的所在 ```typescript import { Effect, Reducer } from 'umi'; import { queryCurrent, query as queryUsers } from '@/services/user'; export interface CurrentUser { avatar?: string; name?: string; title?: string; group?: string; signature?: string; tags?: { key: string; label: string; }[]; userid?: string; unreadCount?: number; } export interface UserModelState { currentUser?: CurrentUser; } //定義介面 export interface UserModelType { namespace: 'user'; state: UserModelState; effects: { fetch: Effect; }; reducers: { saveCurrentUser: Reducer; }; } const UserModel: UserModelType = { //名稱空間,component層呼叫路由方法的時候需要根據名稱空間匹配 namespace: 'user', //存放值的地方 state: { currentUser: {}, }, // 與後臺互動,處理資料邏輯的地方 effects: { //業務方法,這裡的_是不需要引數,如果需要引數,這裡改成傳遞進來的引數物件即可 //這裡支援call,put,select等幾種方法,用call呼叫service層的方法 //const m = yield select((state) => state.test.num) //select就是用來選擇上面state裡的,這裡沒用上 *fetch(_, { call, put }) { //queryUsers是引入service層那個function的一個名字 const response = yield call(queryUsers); yield put({ // 這就是reducer中save方法, put就是用來觸發reducer的方法,payload裡就是傳過去的引數。 同時它也能觸發同等級effects中其他方法。 type: 'saveCurrentUser', payload: response, }); }, }, // 能改變介面的action應該放這裡,這裡按官方意思不應該做資料處理,只是用來return state 從而改變介面 reducers: { //可以理解為一個方法 saveCurrentUser(state, action) { //return新的state,這樣頁面就會更新 es6語法,就是把state全部展開,然後把currentUser重新賦值 return { ...state, currentUser: action.payload || {}, }; }, }, }; export default UserModel; ``` #### component元件中呼叫model層 在某一個方法裡用dispatch即可呼叫 ```typescript clickHandler = () => { dispatch({ type: "user/fetch",// 這裡就會觸發models層裡面effects中fetch方法(也可以直接觸發reducer中方法,看具體情況) ,test就是user裡的名稱空間名字 payload: { }, }) } ``` 這裡注意一下type請求的方法路由即可,前面是名稱空間,後面是方法名 #### 使用connect獲取dispatch呼叫後改變的state中的資料 首先需要在元件介面中定義欄位,型別為model中定義的型別,因為要獲取model中欄位這個值,肯定是同一種類型的 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806142735303-1842978133.png) 然後在元件的實現中定義變數,從props中獲取值 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806142838691-277512198.png) 在元件程式碼下方的connect方法中將變數賦值,只有這裡賦值了,元件中的常量才可以從props中獲取到state中的值 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806142942152-1831726063.png) 這裡connect方法的引數其實就是各個model中的state,dispatch後,這裡便可以獲取到修改後的值 tips:因為使用的是typescript,所以這裡的引數需要在ConnectState中先定義: ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806143105830-561375741.png) ## 【開始改造Antd Pro,實現從伺服器請求選單】 #### 定義service 在src/services資料夾下新增檔案 menu.ts ```typescript import request from '@/utils/request'; export async function query(): Promise { return request('/api/getmenu'); //這裡是服務端的獲取選單的地址,根據自己情況進行調整 } ``` #### 定義model 在src/models資料夾下新增檔案 menu.ts ```typescript import { Effect, Reducer } from 'umi'; import { MenuDataItem } from '@ant-design/pro-layout'; import { query } from '@/services/menu'; export interface MenuModelState { menuData: MenuDataItem[]; } export interface MenuModelType { namespace: 'menu'; state: MenuModelState; effects: { getMenuData: Effect; }; reducers: { saveMenuData: Reducer; }; } //這裡做了個轉換,可能服務端返回的介面格式和前端的路由格式並不一致,可以在這個方法裡進行調整,這裡的方法僅作參考,根據自己實際情況進行調整即可 const menuFormatter = (response: any) => { if (response === null) return []; var re = response.map((item: { name: string; route: string; children: any; }) => { const result = { children: {}, name: item.name, path: item.route === null ? '/' : item.route, }; if (item.children) { result.children = menuFormatter(item.children); } return result; }) return re; } const MenuModel: MenuModelType = { namespace: 'menu', state: { menuData: [], }, effects: { *getMenuData(_, { put, call }) { const response = yield call(query); yield put({ type: 'saveMenuData', payload: menuFormatter(response.data.viewMenu), }); }, }, reducers: { saveMenuData(state, action) { return { ...state, menuData: action.payload || [], }; }, }, }; export default MenuModel; ``` #### 調整元件 BasicLayout.tsx antd pro的選單調整在 src/layouts/BasicLayout.tsx 檔案中 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806141540892-897675422.png) 這裡menuDataRender 預設指向一個方法,我這裡不要原來的方式,我們要調整成自己的資料 以下程式碼如無特殊說明,都在 BasicLayout.tsx 檔案中 ### 1. 調整介面 在 BasicLayoutProps 介面中新增承載選單的欄位 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806141813665-826020347.png) ### 2. 調整元件傳入的欄位,useEfect方法中加入請求服務的路由 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806141935890-1150559489.png) ### 3. 調整元件menuDataRender為使用傳進來的選單資料(以前那個方法不用了) ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806142027514-839117194.png) ### 4. 調整connect方法,獲取資料 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806142134669-305759488.png) menu是我們在models/menu.tx中定義的MenuModelState型別,光這裡寫會提示錯誤,我們需要在ConnectState中先將該欄位定義才可以正常使用 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806142301946-230792288.png) ## 【執行一下試試效果】 執行命令執行一下看看效果 ``` cnpm start ``` 可以看到,已經自動觸發了後端介面,並獲取到了資料,最後又用服務端的資料渲染了選單 ![](https://img2020.cnblogs.com/blog/998608/202008/998608-20200806143526745-2079111306.png) 其他內容可以參考官方文件 antd pro官網地址:[https://pro.ant.design/index-cn](https://pro.ant.design/i