先介紹一個umi,阿里開源的一個企業級可插拔的react腳手架,
umi相對比react官方推薦的腳手架更加的簡單,更貼近vue-cli的使用感受,而本文僅僅介紹基礎使用方法,高手請繞行
開發展示
仿叮咚買菜後臺管理系統預覽: http://dingdong-admin.nodebook.top/
仿叮咚買菜 前臺頁面: http://dingdong.nodebook.top/
叮咚買菜後臺管理系源碼: https://github.com/cgq001/dingdong-admin
叮咚買菜源碼: https://github.com/cgq001/dingdong
功能說明:
演示動圖:
一.介紹
介紹內容來自官網,感興趣可 百度 umi 到官網查看詳情
創建項目:
yarn create umi
選擇 project
? Select the boilerplate type (Use arrow keys)
ant-design-pro - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
❯ app - Create project with a simple boilerplate, support typescript.
block - Create a umi block.
library - Create a library with umi.
plugin - Create a umi plugin.
然後,選擇你需要的功能 這裏 antd 是UI庫 dva 封裝了redux 等
? What functionality do you want to enable? (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ antd
❯◯ dva
◯ code splitting
◯ dll
運行項目
yarn start
目錄
├── dist/ // 默認的 build 輸出目錄
├── mock/ // mock 文件所在目錄,基於 express
├── config/
├── config.js // umi 配置,同 .umirc.js,二選一
└── src/ // 源碼目錄,可選
├── layouts/index.js // 全局佈局
├── pages/ // 頁面目錄,裏面的文件即路由
├── .umi/ // dev 臨時目錄,需添加到 .gitignore
├── .umi-production/ // build 臨時目錄,會自動刪除
├── document.ejs // HTML 模板
├── 404.js // 404 頁面
├── page1.js // 頁面 1,任意命名,導出 react 組件
├── page1.test.js // 用例文件,umi test 會匹配所有 .test.js 和 .e2e.js 結尾的文件
└── page2.js // 頁面 2,任意命名
├── global.css // 約定的全局樣式文件,自動引入,也可以用 global.less
├── global.js // 可以在這裏加入 polyfill
├── app.js // 運行時配置文件
├── .umirc.js // umi 配置,同 config/config.js,二選一
├── .env // 環境變量
└── package.json
使用
一.路由
1.1關於.umirc.js 文件配置
umi 可以使用類似 nuxt.js的約定式路由,當然本次介紹 類似於我們常在vue用使用的配置式路由,即可在這裏配置
具體配置詳情,請看 代碼註釋:
export default {
treeShaking: true,
routes: [ // 配置路由
{ path: '/', //重定向到主頁
redirect: '/index/'
},
{
path: '/index', //主頁
component: '../layouts/index', //公共主頁
// Routes: ['./routes/Login.js'] , //這裏是相對根目錄(非pages)的,文件名後綴不能少
routes: [
// { path: '/index/', component: '../pages/index' },
{ path: '/index/', component: '../pages/Home/HomeIndex/HomeIndex' }, //首頁
{ path: '/index/data/index', component: '../pages/Datas/DataIndex/DataIndex' ,srcPath: '12456'} , //數據分析
{ path: '/index/product/shoping/index', component: '../pages/Product/Shoping/ShopIndex/ShopIndex' }, //商品管理
{ path: '/index/product/shoping/add', component: '../pages/Product/Shoping/AddShop/AddShop' }, //添加商品
{ path: '/index/product/class/index', component: '../pages/Product/Class/ClassIndex/ClassIndex' }, //分類管理
{ path: '/index/product/class/add', component: '../pages/Product/Class/AddClass/AddClass' }, //添加分類
{ path: '/index/product/comment/index', component: '../pages/Product/Comment/CommentIndex/CommentIndex' }, //評論管理
{ path: '/index/set/personalcenter/index', component: '../pages/Set/PersonalCenter/PersonalCenter' }, //個人中心
{ path: '/index/set/PersonalSettings/index', component: '../pages/Set/PersonalSettings/PersonalSettings' }, //個人設置
{ path: '/index/order/refund/index', component: '../pages/Order/Refund/RefundIndex/RefundIndex'} , //待退款列表
{ path: '/index/order/refund/details', component: '../pages/Order/Refund/RefundDetails/RefundDetails'}, //退款詳情
{ path: '/index/order/shipped/index', component: '../pages/Order/Shipped/ShippedIndex/ShippedIndex'} , //待發貨詳情
{ path: '/index/order/shipped/deliver', component: '../pages/Order/Shipped/ShippedDeliver/ShippedDeliver'} , //待發貨詳情
{ path: '/index/control/carousel/index', component: '../pages/Control/Carousel/CarouselIndex/CarouselIndex'} , //佈局控制 首頁輪播 輪播列表
{ path: '/index/control/carousel/add', component: '../pages/Control/Carousel/CarouselAdd/CarouselAdd'} , //佈局控制 首頁輪播 添加輪播圖
{ path: '/index/control/keyword/index', component: '../pages/Control/Keyword/KeywordIndex/KeywordIndex'} , //佈局控制 搜索發現關鍵詞 關鍵詞列表
{ path: '/index/marketing/buy/index', component: '../pages/Marketing/Buy/BuyIndex/BuyIndex'}, //營銷控制 首頁瘋狂搶購 瘋狂搶購列表
{ path: '/index/marketing/buy/add', component: '../pages/Marketing/Buy/BuyAdd/BuyAdd'} //營銷控制 首頁瘋狂搶購 所有商品列表
]
},
{
path: '/login', //登錄頁
component: './Login/Login',
}
],
plugins: [
// ref: https://umijs.org/plugin/umi-plugin-react.html
['umi-plugin-react', {
antd: true, //開啓antd UI庫
dva: true, //開啓dav
dynamicImport: false,
title: '商城管理系統', //title
dll: false,
routes: {
exclude: [
/models\//,
/services\//,
/model\.(t|j)sx?$/,
/service\.(t|j)sx?$/,
/components\//,
],
},
}],
],
"proxy": { //請求代理
"/api": {
"target": "http://192.168.188.200:5005/", //http://192.168.188.200:5005/admin/
"changeOrigin": true,
"pathRewrite": { "^/api" : "" }
}
}
}
1.2關於頁面內的路由跳轉
//引入
import Link from 'umi/link';
import withRouter from 'umi/withRouter';
//使用
<Link to='/index/data/index'>
<Icon type="heat-map" />
<span>數據分析</span>
</Link>
// 最後 生成的 包含Link 的組件 需要子withRouter(組件) 中高階一下即可
1.3導航守衛
在 .umirc.js 文件中聲明的路由中配置: Routes: [’./routes/Login.js’]
然後在 routes/Login.js中進行路由守衛
//例如
path: '/index', //主頁
component: '../layouts/index',
Routes: ['./routes/Login.js'] , //這裏是相對根目錄(非pages)的,文件名後綴不能少
Login.js
export default props => {
if(Math.random > 0.5){ // 大於0.5 去 login 否則去訪問的這個路徑頁面,從而完成導航守衛
return <Redirect to= '/login'></Redirect>
}
return (
<div style={{width: '100%',height: '100%'}}>
{props.children}
</div>
)
}
二.dva
2.1在models/UserRedux.js 文件 存儲全局狀態
// 獲取 本地存儲的 token
let token = localStorage.getItem('token') || sessionStorage.getItem('token')
let global ={
namespace: 'UserRedux', //model的命名空間,區分多個model
state : {
https: 'http://192.168.188.200:5005/', //普通接口
httpsUpload: 'http://192.168.188.200:5005/index/upload', //圖片上傳接口
token: token || null, //token
isLogin: false , //是否正在登錄
userList:{
name: '張三'
}
},
effects:{ // 異步操作
},
reducers: { //更新狀態(同步)
isLogin(state,action){
let stateSrc = state
stateSrc.isLogin = true
return stateSrc
},
removeLogin(state,action){
let stateSrc = state
stateSrc.isLogin = false
return stateSrc
},
setToken(state,action){ //設置token
let stateSrc = state
stateSrc.token = action.token
return stateSrc
},
setUserList(state,action){ //設置用戶信息
let stateSrc = state
stateSrc.userList = action.userList
return stateSrc
}
}
}
export default global;
2.2使用全局狀態
import { connect } from 'dva' //引入dva
export default connect(
state => ({
loading: state.loading , //dva已經可以獲得 loading狀態
UserRedux: state.UserRedux //獲取指定命名空間的模型狀態
}),
{
setUserList: userList => ({
type: 'UserRedux/setUserList', //action的type需要以命名空間爲前綴+reducer名稱
userList //拿到 userList
})
}
)(withRouter(Headers))
this.props.UserRedux.token //即可獲取 UserRedux中的內容
//Headers爲基本組件 withRouter爲路由告誡組件, withRouter(Headers) 需要使用Link跳轉頁面的寫法