螞蟻金服開源的企業級React框架,並不是UI框架
1.特性
- 開箱即用,內置 react、react-router
...
- 類似 next.js 且功能完備的路由約定,同時也支持手動配置路由的方式;
- 完善的插件體系,高性能,通過插件支持PWA、以路由為單元的code splitting等等;
- 支持靜態頁面導出,適配各種環境,如中台業務、無線業務、egg、支付寶錢包
- 開發啟動快,支持一鍵開啟dll
- 一鍵兼容IE9、基於 umi-plugin-polyfills
- 支持TypeScript
- 與 dva 數據流的深入融合,支持duck directory、model的自動加載、code splitting等等

1. State:一個對象,保存整個應用狀態; 2. View:React組件構成的視圖層; 3. Action:一個對象,描述事件 4. connect():綁定```State```到```View``` 5. dispatch():發送```Action```到```State```
3.dva 與 umi 的約定
1.src 源碼:pages(頁面)、components(組件)、layout(布局)、model(數據模型)
2.config 配置
3.mock 數據模擬
4.test 測試
4.全局安裝腳手架: npm i umi -g快速上手
"scripts": { "start": "umi dev", "build": "umi build" }
cd src umi g page index // index.js和index.css umi g page about // bout.js和about.css
5、運行項目:npm start,自動編譯生成頁面配置 /src/pages/.umi 目錄
,且項目是熱部署;
http://localhost:8000/ --> index.js http://localhost:8000/about --> about.js
6、引入公共 css (根據個人需求,可要可不要)
在 src 目錄下新建 global.css/.less
7、創建全局布局 layouts,如公共頭部、尾部 (根據個人需求,可要可不要)
src/layouts 目錄中的 index.js 將成為項目的定級布局頁面,使用 {props.children} 顯示 src/pages 目錄中的組件。
在 src 目錄下,創建文件夾 layouts
在 layouts 目錄下,創建 index.js、index.less
import styles from './index.css'; import {Layout} from 'antd'; const {Header, Content, Footer} = Layout; export default (props) => { return ( <Layout> <Header> <div style={{color: 'white'}}>王者資料庫</div> </Header> <Content style={{padding: '0 50px'}}> {props.children} </Content> <Footer style={{textAlign: 'center'}}>footer</Footer> </Layout> ) }
約定式路由嵌套 (Link、history)
1、當出現 _layout.js 頁面時默認為父組件頁面,通過 {props.children} 顯示子組件內容;
2、嵌套路由:/users,創建 pages/users 目錄
umi g page users/_layout // pages/users/_layout.js、_layout.css
1.pages/users/_layout.js
import React from 'react'; import styles from './_layout.css'; export default (props) => { return ( <div className={styles.normal}> <h1 className={styles.title}>Page users/_layout</h1> <div>{props.children}</div> </div> ); }
2.為 _layout.js 創建子組件,users 的首頁 index.js
umi g page users/index // pages/users/index.js、index.css
3.訪問嵌套路由:http://localhost:8000/users
3、約定 []
包裹的文件或文件夾為動態路由、users/[name].js 對應路由為 /users/:name
- 在 users 目錄中,再創建 [name].js、[name].css
- 訪問 [name].js:http://localhost:8000/users/xxx
4、跳轉路由 (Link,history)
1.users/index.js
import React from 'react'; import styles from './index.css'; import {Link} from 'umi'; export default () => { const userList = [ {id: 1, name: 'Tim'}, {id: 2, name: 'Jarry'} ] return ( <div> <ul> { userList.map(item => ( <li key={item.id}> <Link to={`/users/${item.name}`}>{item.name}</Link> </li> )) } </ul> </div> ); }
2.users/[name].js
import React from 'react'; import styles from './[name].css'; import {history} from 'umi'; export default (props) => { return ( <div> <h1 className={styles.title}>Page users/[name]</h1> <h2>{props.match.params.name}</h2> <button onClick={()=>props.history.goBack()}>返回</button> </div> ); }
配置式路由
1、配置式路由一旦創建,約定式路由自動失效,umi不會再自動創建路由;
2、在項目根目錄下創建 config 目錄,並創建 config.js文件;
// 沒有設置全局 layouts 布局 export default { // 路由配置:路徑相對於 src/pages routes: [ {path: '/', component: './index'}, {path: '/about', component: './about'}, { path: '/users', component: './users/_layout', routes: [ {path: '/users', component: './users/index'}, {path: '/users/:name', component: './users/[name]'}, ] }, {component: './notfound'} // 404頁面,上面的所有路由都沒有匹配時,則匹配404頁面 ], }
// 設置了全局 layouts 布局 export default { // 路由配置:路徑相對於 src/pages routes: [ { path: '/', component: '../layouts/index', routes: [ {path: '/', component: './index'}, {path: '/about', component: './about'}, { path: '/users', component: './users/_layout', routes: [ {path: '/users', component: './users/index'}, {path: '/users/:name', component: './users/[name]'}, ] }, ] }, ], }
3、相應地,創建404組件:umi g page notfound
4、引入ant design UI庫
npm i antd -S
npm i @umijs/preset-react -D (umi3升級)
1.config/config.js
export default { //路由配置 routes: [...], antd: {}, }
2.使用時需要導入組件,因為是按需加載
import {Button} from 'antd';
<Button type="success">antd Btn</Button>
引入dva
1、dva 主要是軟件分層的概念
1.Page 負責與用戶直接交互:渲染頁面、接收用戶的操作輸入,側重於展示型和交互邏輯;
2.Model 負責處理業務邏輯,可以理解成一個維護頁面數據狀態的對象,為 Page 做數據、狀態的讀寫等操作;
export default { namespace: 'goods', // model的命名空間,區分多個model state: [], //初始狀態 effects: { //異步操作 }, reducers: {} }
3.Service 主要負責與HTTP做接口對接,跟后端做數據交互,讀寫數據;
2、dva 已經融合進了 umi,在 config/config.js 中打開 dva 的開關
antd: {},
dva: {}
基本用法
umi g page goods
npm i axios -S
1、路由配置:config/config.js (如果使用約定式路由,則無須配置)
routes: [ { path: "/goods", component: "./goods" }, ]
2、在項目根目錄下創建 mock/goods.js,模擬接收請求,響應數據
let data = [ {title: '單頁面'}, {title: '管理項目3'} ] export default { 'get /api/goods': function(req, res){ setTimeout(() => { res.json({result: data}) }, 1000) } }
3、Model:src/models/goods,js
import axios from 'axios'; //調接口的邏輯應該放在 Service 層 function getGoods(){ return axios.get('/api/goods') } export default{ namespace: 'goods', // 命名空間,如果省略,則以文件名作為命名空間 state: [], effects: { *getList(action, {call , put}){ // 異步操作 const res = yield call(getGoods); // 發起請求 yield put({type: 'initGoods', payload: res.data.result}) // 派發異步action: initGoods } }, reducers: { initGoods(state, action){ return action.payload }, addGood(state, action){ return [...state, {title: action.payload.title}] }, delGood(state, action){ return [...state.slice(0,action.payload.index),...state.slice(action.payload.index+1)]; } } }
4、pages/goods.js
import React, { Component} from 'react'; import styles from './goods.css'; import {connect} from 'dva'; // @connect 必須放在 export default class 前面 @connect( state => ({ goodList: state.goods, // 從指定命名空間內獲取state loading: state.loading // 通過loading命名空間獲取加載的狀態 }), { getList: () => ({ type: 'goods/getList' // action的type需要以命名空間為前綴,后跟reducer }), addGood: title => ({ type: 'goods/addGood', payload: {title} }), delGood: index => ( { type: 'goods/delGood', payload: {index} } ) } ) export default class extends Component{ componentDidMount(){ this.props.getList(); // 觸發事件,發起請求,獲取數據 } render(){ if(this.props.loading.models.goods){ // 命名空間goods 的請求在加載中 return <div>loading</div> } return ( <div> <ul> { this.props.goodList.map((good, index) => { return <li key={index}>{good.title}<button style={{marginLeft: '100px', marginBottom: '10px'}} onClick={() => this.props.delGood(index)}>刪除</button></li> }) } </ul> <button onClick={() => this.props.addGood('商品3')}>添加</button> </div> ) } }
【常見報錯問題】
1、reactjs頁面無法引入umi/link
2、Path must be a string.
【Umi 三】 Umi項目啟動報錯:Path must be a string.
3、Cannot find module 'umi'
【Umi 四】 Cannot find module 'umi'
參考文章:umi