Ant Design Pro總結篇
- Dashboard - 分析頁 - 監控頁 - 工作臺 - 表單頁 - 基礎表單頁 - 分步表單頁 - 高階表單頁 - 列表頁 - 查詢表格 - 標準列表 - 卡片列表 - 搜尋列表(專案/應用/文章) - 詳情頁 - 基礎詳情頁 - 高階詳情頁 - 結果 - 成功頁 - 失敗頁 - 異常 - 403 無許可權 - 404 找不到 - 500 伺服器出錯 - 個人頁 - 個人中心 - 個人設定 - 帳戶 - 登入 - 註冊 - 註冊成功
1.3 使用
$ git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project $ cd my-project
或者
$ npm install ant-design-pro-cli -g $ mkdir my-project && cd my-project $ pro new# 安裝腳手架
1.4 目錄結構
整個專案的目錄結構
├── mock# 本地模擬資料 ├── node_modules# 依賴庫 ├── public │├── favicon.ico# Favicon │└── index.html# HTML 入口模板 ├── src │├── common# 應用公用配置,如導航資訊 │├── components# 業務通用元件 │├── e2e# 整合測試用例 │├── layouts# 通用佈局 │├── models# dva model │├── routes# 業務頁面入口和常用模板 │├── services# 後臺介面服務 │├── utils# 工具庫 │├── g2.js# 視覺化圖形配置 │├── polyfill.js# 相容性墊片 │├── theme.js# 主題配置 │├── index.js# 應用入口 │├── index.less# 全域性樣式 │└── router.js# 路由入口 ├── tests# 測試工具 ├── .editorconfig# 編輯器配置 ├── .eslintrc# js程式碼檢測工具 ├── .ga# 未知 ├── .gitignore# git版本配置 ├── .roadhogrc# roadhog配置 ├── .roadhogrc.mock.js# roadhog的模擬配置 ├── .stylelintrc# css程式碼審查配置 ├── .travis.yml# travis持續構建工具配置 ├── package.json# web前端專案配置檔案 ├── README.md └──
roadhog摘要介紹
-
roadhog
是一個cli
工具,提供server
、build
和 test 三個命令,分別用於本地除錯和構建,並且提供了特別易用的 mock 功能。命令列體驗和create-react-app
一致,配置略有不同,比如預設開啟css
modules
,然後還提供了JSON
格式的配置方式。 - 重點介紹
roadhog
有關的幾個配置項,主要是在ant design pro
的程式碼中用到了這些配置項
entry
- 指定
webpack
入口檔案,支援glob
格式。 - 如果你的專案是多頁型別,會希望把
src/pages
的檔案作為入口。可以這樣配:
"entry": "src/pages/\*.js"
env
針對特定的環境進行配置。 server
的環境變數是 development
, build
的環境變數是 production
。
比如:
"extraBabelPlugins": ["transform-runtime"], "env": { "development": { "extraBabelPlugins": ["dva-hmr"] } }
這樣,開發環境下的 extraBabelPlugins
是 ["transform-runtime", "dva-hmr"]
,而生產環境下是 ["transform-runtime"]
。
"env": { "development": { "extraBabelPlugins": [ "dva-hmr", "transform-runtime", "transform-decorators-legacy", "transform-class-properties", ["import", { "libraryName": "antd", "style": true }] ] }, "production": { "extraBabelPlugins": [ "transform-runtime", "transform-decorators-legacy", "transform-class-properties", ["import", { "libraryName": "antd", "style": true }] ] } }
在這段程式碼中,開發環境和生產環境分別配置,其中開發環境使用了 dva-hmr
外掛
二、佈局
頁面整體佈局是一個產品最外層的框架結構,往往會包含導航、頁尾、側邊欄、通知欄以及內容等。在頁面之中,也有很多區塊的佈局結構。在真實專案中,頁面佈局通常統領整個應用的介面,有非常重要的作用
2.1 Ant Design Pro 的佈局
在 Ant Design Pro 中,我們抽離了使用過程中的通用佈局,都放在 layouts
目錄中,分別為
BasicLayout:基礎頁面佈局,包含了頭部導航,側邊欄和通知欄
UserLayout:抽離出用於登陸註冊頁面的通用佈局
BlankLayout:空白的佈局
2.2 如何使用 Ant Design Pro 佈局
通常佈局是和路由系統緊密結合的,Ant Design Pro 的路由使用了 Umi
的路由方案,為了統一方便的管理路由和頁面的關係,我們將配置資訊統一抽離到 config/router.config.js
下,通過如下配置定義每個頁面的佈局
module.exports = [{ path: '/', component: '../layouts/BasicLayout',// 指定以下頁面的佈局 routes: [ // dashboard { path: '/', redirect: '/dashboard/analysis' }, { path: '/dashboard', name: 'dashboard', icon: 'dashboard', routes: [ { path: '/dashboard/analysis', name: 'analysis', component: './Dashboard/Analysis' }, { path: '/dashboard/monitor', name: 'monitor', component: './Dashboard/Monitor' }, { path: '/dashboard/workplace', name: 'workplace', component: './Dashboard/Workplace' }, ], }, ], }]
更多 Umi 的路由配置方式可以參考: Umi 配置式路由
2.3 Pro 擴充套件配置
我們在 router.config.js
擴充套件了一些關於 pro
全域性選單的配置
{ name: 'dashboard', icon: 'dashboard', hideInMenu: true, hideChildrenInMenu: true, hideInBreadcrumb: true, authority: ['admin'], }
-
name
: 當前路由在選單和麵包屑中的名稱,注意這裡是國際化配置的key
,具體展示選單名可以在/src/locales/zh-CN.js
進行配置。 -
icon
: 當前路由在選單下的圖示名。 -
hideInMenu
: 當前路由在選單中不展現,預設false
。 -
hideChildrenInMenu
: 當前路由的子級在選單中不展現,預設false
。 -
hideInBreadcrumb
: 當前路由在麵包屑中不展現,預設false
。 -
authority
: 允許展示的許可權,不設則都可見,詳見:許可權管理
2.4 Ant Design 佈局元件
除了 Pro 裡的內建佈局以為,在一些頁面中需要進行佈局,可以使用 Ant Design 目前提供的兩套佈局元件工具: Layout
和 Grid
Grid 元件
- 柵格佈局是網頁中最常用的佈局,其特點就是按照一定比例劃分頁面,能夠隨著螢幕的變化依舊保持比例,從而具有彈性佈局的特點。
- 而 Ant Design 的柵格元件提供的功能更為強大,能夠設定間距、具有支援響應式的比例設定,以及支援 flex 模式,基本上涵蓋了大部分的佈局場景 https://ant.design/components/grid/
Layout 元件
如果你需要輔助頁面框架級別的佈局設計,那麼 Layout 則是你最佳的選擇,它抽象了大部分框架佈局結構,使得只需要填空就可以開發規範專業的頁面整體佈局 https://ant.design/components/layout-cn/
- 根據不同場景區分抽離佈局元件#
在大部分場景下,我們需要基於上面兩個元件封裝一些適用於當下具體業務的元件,包含了通用的導航、側邊欄、頂部通知、頁面標題等元素。例如 Ant Design Pro 的BasicLayout
。 - 通常,我們會把抽象出來的佈局元件,放到跟 pages、 components 平行的 layouts 資料夾中方便管理。需要注意的是,這些佈局元件和我們平時使用的其它元件並沒有什麼不同,只不過功能性上是為了處理佈局問題
四、路由和選單
路由和選單是組織起一個應用的關鍵骨架,pro 中的路由為了方便管理,使用了中心化的方式,在 router.config.js
統一配置和管理
4.1 基本結構
- 路由管理 通過約定的語法根據在
router.config.js
中配置路由。 - 選單生成 根據路由配置來生成選單。選單項名稱,巢狀路徑與路由高度耦合。
- 麵包屑 元件 PageHeader 中內建的麵包屑也可由腳手架提供的配置資訊自動生成
4.1.1 路由
目前腳手架中所有的路由都通過 router.config.js
來統一管理,在 umi
的配置中我們增加了一些引數,如 name
, icon
, hideChildren
, authority
,來輔助生成選單。其中
-
name
和icon
分別代表生成選單項的圖示和文字。 -
hideChildren
用於隱藏不需要在選單中展示的子路由。用法可以檢視 分步表單 的配置。 -
hideInMenu
可以在選單中不展示這個路由,包括子路由。效果可以檢視exception/trigger
頁面。 -
authority
用來配置這個路由的許可權,如果配置了將會驗證當前使用者的許可權,並決定是否展示
4.1.2 選單
選單根據 router.config.js
生成,具體邏輯在 src/layouts/BasicLayout
中的 formatter
方法實現
- 如果你的專案並不需要選單,你可以直接在
BasicLayout
中刪除SiderMenu
元件的掛載。並在src/layouts/BasicLayout
中 設定const MenuData = []
。 - 如果你需要從伺服器請求選單,可以將
menuData
設定為state
,然後通過網路獲取來修改了state
4.1.3 麵包屑
麵包屑由 PageHeaderLayout
實現, MenuContext
將 根據 MenuData
生成的 breadcrumbNameMap
通過 props
傳遞給了 PageHeader
,如果你要做自定義的麵包屑,可以通過修改傳入的 breadcrumbNameMap
來解決
breadcrumbNameMap
示例資料如下:
{ '/': { path: '/', redirect: '/dashboard/analysis', locale: 'menu' }, '/dashboard/analysis': { name: 'analysis', component: './Dashboard/Analysis', locale: 'menu.dashboard.analysis', }, ... }
4.2 需求例項
4.2.1 新增頁面
腳手架預設提供了兩種佈局模板:基礎佈局 - BasicLayout
以及 賬戶相關佈局 - UserLayout
如果你的頁面可以利用這兩種佈局,那麼只需要在路由配置中增加一條即可
// app { path: '/', component: '../layouts/BasicLayout', routes: [ // dashboard { path: '/', redirect: '/dashboard/analysis' }, { path :'/dashboard/test',component:"./Dashboard/Test"}, ... },
加好後,會預設生成相關的路由及導航
4.2.2 新增佈局
在腳手架中我們通過巢狀路由來實現佈局模板。 router.config.js
是一個數組,其中第一級資料就是我們的佈局,如果你需要新增佈局可以在直接增加一個新的一級陣列
module.exports = [ // user { path: '/user', component: '../layouts/UserLayout', routes:[...] }, // app { path: '/', component: '../layouts/BasicLayout', routes:[...] }, // new { path: '/new', component: '../layouts/new_page', routes:[...] }, ]
4.2.3 帶引數的路由
腳手架預設支援帶引數的路由,但是在選單中顯示帶引數的路由並不是個好主意,我們並不會自動的幫你注入一個引數,你可能需要在程式碼中自行處理
{ path: '/dashboard/:page', hideInMenu:true, name: 'analysis', component: './Dashboard/Analysis' },
你可以通過以下程式碼來跳轉到這個路由
import router from 'umi/router'; router.push('/dashboard/anyParams') //or import Link from 'umi/link'; <Link to="/dashboard/anyParams">go</Link>
在路由元件中,可以通過 this.props.match.params
來獲得路由引數
五、新增頁面
這裡的『頁面』指配置了路由,能夠通過連結直接訪問的模組,要新建一個頁面,通常只需要在腳手架的基礎上進行簡單的配置
5.1 新增 js、less
在 src/pages
下新建頁面的 js
及 less
檔案,如果相關頁面有多個,可以新建一個資料夾來放置相關檔案
樣式檔案預設使用 CSS Modules,如果需要,你可以在樣式檔案的頭部引入 antd 樣式變數檔案
@import "~antd/lib/style/themes/default.less";
5.2 將檔案加入選單和路由
加入選單和路由的方式請參照 路由和選單 - 新增路由/選單 中的介紹完成。加好後,訪問 http://localhost:8000/#/new
就可以看到新增的頁面了 https://pro.ant.design/docs/router-and-nav-cn#%E6%B7%BB%E5%8A%A0%E8%B7%AF%E7%94%B1/%E8%8F%9C%E5%8D%95
5.3 新增 model、service
佈局及路由都配置好之後,回到之前新建的 NewPage.js
,可以開始寫業務程式碼了!如果需要用到 dva
中的資料流,還需要在 src/models src/services
中建立相應的 model
和 service,具體可以參考腳手架內建頁面的寫法
六、新增業務元件
對於一些可能被多處引用的功能模組,建議提煉成業務元件統一管理。這些元件一般有以下特徵:
- 只負責一塊相對獨立,穩定的功能;
- 沒有單獨的路由配置;
- 可能是純靜態的,也可能包含自己的 state,但不涉及 dva 的資料流,僅受父元件(通常是一個頁面)傳遞的引數控制。
新建檔案
在 src/components
下新建一個以元件名命名的資料夾,注意首字母大寫,命名儘量體現元件的功能,這裡就叫 ImageWrapper
。在此資料夾下新增 js 檔案及樣式檔案(如果需要),命名為 index.js
和 index.less
- 在使用元件時,預設會在
index.js
中尋找export
的物件,如果你的元件比較複雜,可以分為多個檔案,最後在index.js
中統一export
,就像這樣
// MainComponent.js export default ({ ... }) => (...); // SubComponent1.js export default ({ ... }) => (...); // SubComponent2.js export default ({ ... }) => (...); // index.js import MainComponent from './MainComponent'; import SubComponent1 from './SubComponent1'; import SubComponent2 from './SubComponent2'; MainComponent.SubComponent1 = SubComponent1; MainComponent.SubComponent2 = SubComponent2; export default MainComponent;
你的程式碼大概是這個樣子
// index.js import React from 'react'; import styles from './index.less';// 按照 CSS Modules 的方式引入樣式檔案。 export default ({ src, desc, style }) => ( <div style={style} className={styles.imageWrapper}> <img className={styles.img} src={src} alt={desc} /> {desc && <div className={styles.desc}>{desc}</div>} </div> );
// index.less .imageWrapper { padding: 0 20px 8px; background: #f2f4f5; width: 400px; margin: 0 auto; text-align: center; } .img { vertical-align: middle; max-width: calc(100% - 32px); margin: 2.4em 1em; box-shadow: 0 8px 20px rgba(143, 168, 191, 0.35); }
使用
在要使用這個元件的地方,按照元件定義的 API
傳入引數,直接使用就好,不過別忘了先引入
import React from 'react'; import ImageWrapper from '@/components/ImageWrapper';// @ 表示相對於原始檔根目錄 export default () => ( <ImageWrapper src="https://os.alipayobjects.com/rmsportal/mgesTPFxodmIwpi.png" desc="示意圖" /> );
七、樣式
less
Ant Design Pro 預設使用 less 作為樣式語言
CSS Modules
在樣式開發過程中,有兩個問題比較突出
- 全域性汙染 —— CSS 檔案中的選擇器是全域性生效的,不同檔案中的同名選擇器,根據 build 後生成檔案中的先後順序,後面的樣式會將前面的覆蓋;
- 選擇器複雜 —— 為了避免上面的問題,我們在編寫樣式的時候不得不小心翼翼,類名裡會帶上限制範圍的標識,變得越來越長,多人開發時還很容易導致命名風格混亂,一個元素上使用的選擇器個數也可能越來越多。
為了解決上述問題,我們的腳手架預設使用 CSS Modules 模組化方案,先來看下在這種模式下怎麼寫樣式
// example.js import styles from './example.less'; export default ({ title }) => <div className={styles.title}>{title}</div>;
// example.less .title { color: @heading-color; font-weight: 600; margin-bottom: 16px; }
- 用 less 寫樣式好像沒什麼改變,只是類名比較簡單(實際專案中也是這樣),js 檔案的改變就是在設定
className
時,用一個物件屬性取代了原來的字串,屬性名跟 less 檔案中對應的類名相同,物件從 less 檔案中引入。 - 在上面的樣式檔案中,
.title
只會在本檔案生效,你可以在其他任意檔案中使用同名選擇器,也不會對這裡造成影響。不過有的時候,我們就是想要一個全域性生效的樣式呢?可以使用:global
// example.less .title { color: @heading-color; font-weight: 600; margin-bottom: 16px; } /* 定義全域性樣式 */ :global(.text) { font-size: 16px; } /* 定義多個全域性樣式 */ :global { .footer { color: #ccc; } .sider { background: #ebebeb; } }
CSS Modules 的基本原理很簡單,就是對每個類名(非 :global
宣告的)按照一定規則進行轉換,保證它的唯一性。如果在瀏覽器裡檢視這個示例的 dom 結構,你會發現實際渲染出來是這樣的
<div class="title___3TqAx">title</div>
- 類名被自動添加了一個
hash
值,這保證了它的唯一性
樣式檔案類別
在一個專案中,樣式檔案根據功能不同,可以劃分為不同的類別
-
src/index.less#
全域性樣式檔案,在這裡你可以進行一些通用設定,比如腳手架中自帶的
html, body, :global(#root) { height: 100%; } body { text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } // temporary font size patch :global(.ant-tag) { font-size: 12px; }
-
src/utils/utils.less#
這裡可以放置一些工具函式供呼叫,比如清除浮動 .clearfix
- 模組樣式
針對某個模組/頁面生效的檔案
八、和服務端進行互動
前端請求流程
在 Ant Design Pro 中,一個完整的前端 UI 互動到服務端處理流程是這樣的
- UI 元件互動操作;
- 呼叫
model
的effect
; - 呼叫統一管理的
service
請求函式; - 使用封裝的
request.js
傳送請求; - 獲取服務端返回;
- 然後呼叫
reducer
改變state
; - 更新
model
為了方便管理維護,統一的請求處理都放在 services 資料夾中,並且一般按照 model 維度進行拆分檔案
services/ user.js api.js ...
其中, utils/request.js
是基於 fetch
的封裝,便於統一處理 POST,GET 等請求引數,請求頭,以及錯誤提示資訊等
// services/user.js import request from '../utils/request'; export async function query() { return request('/api/users'); } export async function queryCurrent() { return request('/api/currentUser'); } // models/user.js import { queryCurrent } from '../services/user'; ... effects: { *fetch({ payload }, { call, put }) { ... const response = yield call(queryUsers); ... }, }
處理非同步請求
在處理複雜的非同步請求的時候,很容易讓邏輯混亂,陷入巢狀陷阱,所以 Ant Design Pro
的底層基礎框架 dva
使用 effect
的方式來管理同步化非同步請求
effects: { *fetch({ payload }, { call, put }) { yield put({ type: 'changeLoading', payload: true, }); // 非同步請求 1 const response = yield call(queryFakeList, payload); yield put({ type: 'save', payload: response, }); // 非同步請求 2 const response2 = yield call(queryFakeList2, payload); yield put({ type: 'save2', payload: response2, }); yield put({ type: 'changeLoading', payload: false, }); }, },
九、引入外部模組
除了 antd
元件以及腳手架內建的業務元件,有時我們還需要引入其他外部模組,這裡以引入富文字元件 react-quill
為例進行介紹
$ npm install react-quill --save
import React from 'react'; import { Button, notification, Card } from 'antd'; import ReactQuill from 'react-quill'; import 'react-quill/dist/quill.snow.css'; export default class NewPage extends React.Component { state = { value: 'test', }; handleChange = (value) => { this.setState({ value, }) }; prompt = () => { notification.open({ message: 'We got value:', description: <span dangerouslySetInnerHTML={{ __html: this.state.value }}></span>, }); }; render() { return ( <Card title="富文字編輯器"> <ReactQuill value={this.state.value} onChange={this.handleChange} /> <Button style={{ marginTop: 16 }} onClick={this.prompt}>Prompt</Button> </Card> ); } }
十、圖表
Ant Design Pro 提供了由設計師精心設計抽象的圖表型別,是在 BizCharts
圖表庫基礎上的二次封裝,同時提供了業務中常用的圖表套件,可以單獨使用,也可以組合起來實現複雜的展示效果
圖表元件 https://pro.ant.design/components/Charts-cn/
使用 Ant Design Pro 的圖表
Charts 圖表套件是在 components/Charts
包中,引用到專案就像使用其它元件一樣
import { ChartCard, MiniBar } from '@/components/Charts'; import { Tooltip, Icon } from 'antd'; const visitData = [ { x: "2017-09-01", y: 100 }, { x: "2017-09-02", y: 120 }, { x: "2017-09-03", y: 88 }, { x: "2017-09-04", y: 65 } ]; ReactDOM.render( <ChartCard title="支付筆數" action={ <Tooltip title="支付筆數反應交易質量"> <Icon type="exclamation-circle-o" /> </Tooltip> } total="6,500" contentHeight={46} > <MiniBar height={46} data={visitData} /> </ChartCard>, mountNode );
https://github.com/alibaba/BizCharts
使用 BizCharts 繪製圖表
如果 Ant Design Pro
不能滿足你的業務需求,可以直接使用 BizCharts
封裝自己的圖表元件。
npm install bizcharts --save
import { Chart, Axis, Tooltip, Geom } from 'bizcharts'; const data = [...]; <Chart height={400} data={data} forceFit> <Axis name="month" /> <Axis name="temperature" label={{ formatter: val => `${val}°C` }} /> <Tooltip crosshairs={{ type : "y" }} /> <Geom type="line" position="month*temperature" size={2} color={'city'} /> <Geom type='point' position="month*temperature" size={4} color={'city'} /> </Chart>
十一、業務圖示
通常情況下,你可以通過 Ant Design
提供的 <Icon />
圖示元件來使用 Ant Design 官方圖示。基本使用方式如下:
<Icon type="heart" style={{ fontSize: '16px', color: 'hotpink' }} />
如果你沒有在 Ant Design
官方圖示中找到需要的圖示,可以到 iconfont.cn
上採集並生成自己的業務圖示庫,再進行使用
生成圖示庫程式碼
- 首先,搜尋並找到你需要的圖示,將它採集到你的購物車裡,在購物車裡,你可以將選中的圖示新增到專案中(沒有的話,新建一個),後續生成的資源/程式碼都是以專案為維度的。
- 如果你已經有了設計稿,只是需要生成相關程式碼,可以上傳你的圖示後,再進行上面的操作
來到剛才選中的專案頁,點選『生成程式碼』的連結,會在下方生成不同引入方式的程式碼,下面會分別介紹
引入
SVG 符號引入是現代瀏覽器未來主流的圖示引入方式。其方法是預先載入符號,在合適的地方引入並渲染為向量圖形。有如下特點:
- 支援多色圖示,不再受到單色圖示的限制
- 通過一些技巧,支援像字型那樣,通過
font-size
、color
來調整樣式 - 支援IE 9+ 及現代瀏覽器
切換到 Symbol
頁籤,複製專案生成的地址程式碼:
//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.js
加入圖示樣式程式碼,如果沒有特殊的要求,你可以直接複用 Ant Design 圖示的樣式
.icon { width: 1em; height: 1em; fill: currentColor; vertical-align: -.125em; }
挑選相應圖示並獲取類名,應用於頁面
<svg class="icon" aria-hidden="true"> <use xlink:href="#icon-ali-pay"></use> </svg>
你也可以通過使用 Ant Design 圖示元件提供的 Icon.createFromIconfontCN({...})
方法來更加方便地使用圖示,使用方式如下:
import { Icon } from 'antd'; const IconFont = Icon.createFromIconfontCN({ scriptUrl: '//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.js' }); export default IconFont;
之後可以像使用 <Icon />
元件一樣方便地使用,支援配置樣式
<IconFont type="icon-ali-pay" style={{ fontSize: '16px', color: 'lightblue' }} />
瞭解更多用法 https://pro.ant.design/docs/biz-icon-cn#%E4%BA%8C%E3%80%81%E5%BC%95%E5%85%A5
十二、Mock 和聯調
Mock 資料是前端開發過程中必不可少的一環,是分離前後端開發的關鍵鏈路。通過預先跟伺服器端約定好的介面,模擬請求資料甚至邏輯,能夠讓前端開發獨立自主,不會被服務端的開發所阻塞
- 在
Ant Design Pro
中,因為我們的底層框架是umi
,而它自帶了代理請求功能,通過代理請求就能夠輕鬆處理資料模擬的功能
使用 umi 的 mock 功能
umi 里約定 mock 資料夾下的檔案即 mock 檔案,檔案匯出介面定義,支援基於 require 動態分析的實時重新整理,支援 ES6 語法,以及友好的出錯提示
export default { // 支援值為 Object 和 Array 'GET /api/users': { users: [1, 2] }, // GET POST 可省略 '/api/users/1': { id: 1 }, // 支援自定義函式,API 參考 express@4 'POST /api/users/create': (req, res) => { res.end('OK'); }, };
當客戶端(瀏覽器)傳送請求,如: GET /api/users
,那麼本地啟動的 umi dev 會跟此配置檔案匹配請求路徑以及方法,如果匹配到了,就會將請求通過配置處理,就可以像樣例一樣,你可以直接返回資料,也可以通過函式處理以及重定向到另一個伺服器
瞭解更多 https://pro.ant.design/docs/mock-api-cn#%E4%BD%BF%E7%94%A8-umi-%E7%9A%84-mock-%E5%8A%9F%E8%83%BD
十三、主題定製
我們基於 Ant Design React 進行開發,完全支援官方提供的 less 變數定製功能. 你可以在腳手架目錄中找到 config/config.js
程式碼類似這樣
... theme: { 'font-size-base': '14px', 'badge-font-size': '12px', 'btn-font-size-lg': '@font-size-base', 'menu-dark-bg': '#00182E', 'menu-dark-submenu-bg': '#000B14', 'layout-sider-background': '#00182E', 'layout-body-background': '#f0f2f5', }; ...
十四、許可權管理
只需要在配置選單的時候配置上准入身份,在登入成功以後獲取到登陸者身份以後更新登入人身份引數即可
許可權元件 Authorized
這是腳手架許可權管理的基礎,基本思路是通過比對當前許可權與准入許可權,決定展示正常渲染內容還是異常內容
控制選單和路由顯示
如需對某些頁面進行許可權控制,只須在路由配置檔案 router.config.js
中設定 authority
屬性即可,代表該路由的准入許可權,pro 的路由系統中會預設包裹 Authorized
進行判斷處理。
{ path: '/form', icon: 'form', name: 'form', routes:[{ path: '/form/basic-form', name: 'basicform', component: './Forms/BasicForm', }, { path: '/form/step-form', name: 'stepform', component: './Forms/StepForm', authority: ['guest'], // 配置准入許可權,可以配置多個角色 }, { path: '/form/advanced-form', name: 'advancedform', component: './Forms/AdvancedForm', authority: ['admin'], // 配置准入許可權,可以配置多個角色 }], }
控制頁面元素顯示
使用 Authorized
或 Authorized.Secured
可以很方便地控制元素/元件的渲染。 https://pro.ant.design/components/Authorized#Authorized.Secured
demo關於許可權簡介
- 用郵箱自己註冊賬戶(註冊後可以登入但是沒有任何許可權)
guest
- 聯絡管理員分配許可權(分配後可以檢視有許可權的頁面)
- 每次登入後獲取最新的許可權身份(如:
admin
,user
,guest
)
在 src/router.js
中會發現如下程式碼
<AuthorizedRoute path="/" render={props => <BasicLayout {...props} />} authority={['admin', 'user', 'guest']} redirectPath="/user/login" />
其中 authority
物件就是准入身份的陣列,表示只有這些身份的人可以登入,我們在配置的時候一定不要忘記在這更新我們新增的身份
- 然後就是
menu.js
,如下,展示了我們在配置選單的時候怎麼配身份
const menuData = [{ name: '題庫管理', path: 'question', icon: 'warning', authority: ['admin', 'user'], children: [{ name: '題庫列表', path: 'list', }, { name: '編輯題目', path: 'create-question', hideInMenu: true, }, { name: '科目管理' }] }, { name: '賬號管理', icon: 'warning', path: 'account', children: [{ name: '賬號列表', path: 'list', authority: 'admin', }, { name: '建設中', path: '', authority: ['admin', 'user'], }] }]
登入成功以後怎麼獲取許可權了
effects:{ * login({payload}, {call, put}) { const response = yield call(login, payload); yield put({ type: 'changeLoginStatus', payload: response, }); // 登入成功以後更新許可權,跳轉頁面 if (response && response.code === '0000') { reloadAuthorized(); yield put(routerRedux.push('/')); } }, }, reducers: { changeLoginStatus(state, {payload}) { let _status = "ok"; let _user = "admin"; setToken("token"); setAuthority(_user);//設定許可權 return { ...state, status: _status, type: 'account', }; }, }
- 我們看看
setAuthority
、reloadAuthorized
這兩個方法都做了什麼事兒
//設定身份 export function setAuthority(authority) { return localStorage.setItem('antd-pro-authority', authority); } //獲取身份 export function getAuthority() { return localStorage.getItem('antd-pro-authority'); }
如此而且,只是把新的身份值存在 localStorage
裡邊,注意 getAuthority
,下邊會用到
import RenderAuthorized from '../components/Authorized'; import { getAuthority } from './authority'; let Authorized = RenderAuthorized(getAuthority()); const reloadAuthorized = () => { Authorized = RenderAuthorized(getAuthority()); }; export { reloadAuthorized }; export default Authorized; RenderAuthorized: (currentAuthority: string | () => string) => Authorized
許可權元件預設 export RenderAuthorized
函式,它接收當前許可權作為引數,返回一個許可權物件,該物件提供以下幾種使用方式
Authorized
最基礎的許可權控制
引數 | 說明 |
---|---|
children |
正常渲染的元素,許可權判斷通過時展示 |
authority |
准入許可權/許可權判斷 |
noMatch |
許可權異常渲染元素,許可權判斷不通過時展示 |
Authorized.AuthorizedRoute
引數 | 說明 |
---|---|
authority |
准入許可權/許可權判斷 |
redirectPath |
許可權異常時重定向的頁面路由 |
Authorized.Secured
註解方式, `@Authorized.Secured (authority, error)`
引數 | 說明 |
---|---|
authority |
准入許可權/許可權判斷 |
error |
許可權異常時渲染元素 |
Authorized.check
函式形式的 Authorized
,用於某些不能被 HOC
包裹的元件。 Authorized.check(authority, target, Exception)
- 注意:傳入一個
Promise
時,無論正確還是錯誤返回的都是一個ReactClass
引數 | 說明 |
---|---|
authority |
准入許可權/許可權判斷 |
target |
許可權判斷通過時渲染的元素 |
Exception |
許可權異常時渲染元素 |
十五、構建和釋出
構建
當專案開發完畢,只需要執行一行命令就可以打包你的應用:
$ npm run build
由於 Ant Design Pro 使用的工具 Umi 已經將複雜的流程封裝完畢,構建打包檔案只需要一個命令 umi build,構建打包成功之後,會在根目錄生成 dist 資料夾,裡面就是構建打包好的檔案,通常是 .js、 .css、index.html 等靜態檔案
分析構建檔案體積
如果你的構建檔案很大,你可以通過 analyze 命令構建並分析依賴模組的體積分佈,從而優化你的程式碼。
$ npm run analyze
釋出
對於釋出來講,只需要將最終生成的靜態檔案,也就是通常情況下 dist 資料夾的靜態檔案釋出到你的 cdn 或者靜態伺服器即可,需要注意的是其中的 index.html
通常會是你後臺服務的入口頁面,在確定了 js 和 css 的靜態之後可能需要改變頁面的引入路徑
前端路由與服務端的結合
Ant Design Pro 使用的 Umi 支援兩種路由方式: browserHistory
和 hashHistory
。
- 可以在
config/config.js
中進行配置選擇用哪個方式:
export default { history: 'hash', // 預設是 browser }
十六、一些問題
在ant-design-pro中解決跨域辦法
需要在配置檔案中( .webpackrc
)加入如下程式碼
"proxy": { "/api": { "target": "http://xxx:xx/", "changeOrigin": true, "pathRewrite": { "^/api" : "" } } },
需要注意的是此處不是將 /api/
代理到正式請求 /api/
中,(例如請求 /api/users
則會代理到 http://xxx:xx/users
)
如果需要多次代理且需要代理到不同的伺服器則可以在配置檔案中進行如下配置
"proxy": { "/test": { "target": "http://xxx:xx/", "changeOrigin": true, "pathRewrite": { "^/test" : "" } }, "/cross": { "target": "http://jsonplaceholder.typicode.com", "changeOrigin": true, "pathRewrite": {"^/cross": ""} } // 此處有一點需要注意,不能在最後一個代理物件後面加逗號,否則會報錯!!! },
在model中怎麼同時發起多次請求
因為 yield
將非同步請求轉為同步請求了,所以請求會按照同步順序依次執行,使請求時間延長
錯誤寫法
// effects將按順序執行 const response = yield call(fetch, '/users'); const res = yield call(fetch, '/roles');
正確寫法
// effects將會同步執行 const [response, res] = yield [ call(fetch, '/users'), call(fetch, '/roles'), ]