首先創建一個使用ant-designUI框架的項目,創建過程見https://blog.csdn.net/qq_41957257/article/details/105322193,根據這個過程,項目已經包括less處理器、Jest單元測試等功能,還可實現按需加載。下面,我們就在這個的基礎上逐步搭建Vue版的ant-design-pro。
一.可擴展性路由創建
ant-design-pro包括如下模塊:
- Dashboard
- 分析頁
- 監控頁
- 工作臺
- 表單頁
- 基礎表單頁
- 分步表單頁
- 高級表單頁
- 列表頁
- 查詢表格
- 標準列表
- 卡片列表
- 搜索列表(項目/應用/文章)
- 詳情頁
- 基礎詳情頁
- 高級詳情頁
- 結果
- 成功頁
- 失敗頁
- 異常
- 403 無權限
- 404 找不到
- 500 服務器出錯
- 個人頁
- 個人中心
- 個人設置
- 圖形編輯器
- 流程圖編輯器
- 腦圖編輯器
- 拓撲編輯器
- 帳戶
- 登錄
- 註冊
- 註冊成功
每個模塊在項目中都在Views下有一個文件夾與之相應,我們就實現其中五個模塊,如下所示
相應地,也對應一段路由,如dashboard模塊就對應於/dashboard,用戶模塊就對應於/user,同時爲了邏輯清晰,每個模塊下的各個頁在路由上都作爲模塊的孩子路由,如用戶模塊的路由寫法如下:
{
path: "/user",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/UserLayout"),
children: [
{
path: "/user",
redirect: "/user/login"
},
{
path: "/user/login",
name: "login",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Login")
},
{
path: "/user/register",
name: "register",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Register")
},
{
path: "/user/register-result",
name: "register.result",
component: () =>
import(
/* webpackChunkName: "user" */ "../views/User/RegisterResult"
)
}
]
用戶模塊路由是/user,我們採用用戶佈局(後面實現),其下面的頁l路由都作爲用戶模塊的孩子,如登錄就是/user/login,對應User文件夾下的Login組件,這樣的好處是非常清晰,而且如果你想在用戶模塊下增加新的頁面,路由擴展起來就非常方便,只需將新頁面的路由放到children裏即可。
這裏還寫了一個重定向,即如果你輸入/user就會重定向到/user/login中。
其他的路由寫法也類似,代碼如下:
import Vue from "vue";
import VueRouter from "vue-router";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
Vue.use(VueRouter);
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/BasicLayout"),
children: [
// dashboard
{
path: "/",
redirect: "/dashboard/analysis"
},
{
path: "/dashboard",
name: "dashboard",
component: { render: h => h("router-view") },
children: [
{
path: "/dashboard/analysis",
name: "analysis",
component: () =>
import(
/* webpackChunkName: "dashboard" */ "../views/Dashboard/Analysis"
)
}
]
},
// form
{
path: "/form",
name: "form",
component: { render: h => h("router-view") },
children: [
{
path: "/form/basic-form",
name: "basicForm",
component: () =>
import(
/* webpackChunkName: "form" */ "../views/Forms/BasicForm"
)
},
{
path: "/form/step-form",
name: "stepForm",
component: () =>
import(
/* webpackChunkName: "form" */ "../views/Forms/StepForm"
),
children: [
{
path: "/form/step-form",
redirect: "/form/step-form/info"
},
{
path: "/form/step-form/info",
name: "info",
component: () =>
import(
/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step1"
)
},
{
path: "/form/step-form/confirm",
name: "confirm",
component: () =>
import(
/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step2"
)
},
{
path: "/form/step-form/result",
name: "result",
component: () =>
import(
/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step3"
)
}
]
}
]
},
// Exception
{
path: "/exception",
name: "exception",
component: { render: h => h("router-view") },
redirect: "/exception/403",
children: [
{
path: "/exception/403",
name: "exception403",
component: () =>
import(
/* webpackChunkName: "exception" */ "../views/Exception/403"
),
},
{
path: "/exception/404",
name: "exception404",
component: () =>
import(
/* webpackChunkName: "exception" */ "../views/Exception/404"
),
},
{
path: "/exception/500",
name: "exception500",
component: () =>
import(
/* webpackChunkName: "exception" */ "../views/Exception/500"
),
}
]
},
// Profile
{
path: "/profile",
name: "profile",
component: { render: h => h("router-view") },
redirect: "/profile/basic",
children: [
{
path: "/profile/basic",
name: "basic",
component: () =>
import(
/* webpackChunkName: "profile" */ "../views/Profile/BasicProfile"
),
},
{
path: "/profile/advanced",
name: "advanced",
component: () =>
import(
/* webpackChunkName: "profile" */ "../views/Profile/AdvancedProfile"
),
meta: { title: "高級詳情頁" }
}
]
},
{
path: "/user",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/UserLayout"),
children: [
{
path: "/user",
redirect: "/user/login"
},
{
path: "/user/login",
name: "login",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Login")
},
{
path: "/user/register",
name: "register",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Register")
},
{
path: "/user/register-result",
name: "register.result",
component: () =>
import(
/* webpackChunkName: "user" */ "../views/User/RegisterResult"
)
}
]
}
]
},
{
path: "/403",
name: "403",
component: () =>
import(/* webpackChunkName: "exception" */ "../views/Exception/403")
},
{
path: "*",
name: "404",
component: () =>
import(/* webpackChunkName: "exception" */ "../views/Exception/404")
}
]
});
export default router;
這裏我們看到了下面這串代碼,這實際上就是調用了render函數來渲染,如同直接使用包含<router-view></router-view>的組件
{ render: h => h("router-view") }
我們除了正常的模塊,還包括了404,就是訪問地址不存在時就會跳轉到404。
好,我們路由寫好後就按照路由的配置相應去創建各個文件,views文件夾下的截圖如下所示:
我們在路由上還看到好幾個佈局文件,因此我們創建layouts文件夾,裏面放上用到的BasicLayout和UserLayout,由於我們所有的佈局都包括頭部、側邊菜單和尾部,我們需要把他們抽離出來,因此我們在layouts下新增Footer.vue、SiderMenu.Vue和Header.vue文件,layouts文件夾截圖如下所示:
我們把這三個組件在BasicLayout中引入,代碼如下:
<template>
<div>
<Header></Header>
<SiderMenu></SiderMenu>
<router-view></router-view>
<Footer></Footer>
</div>
</template>
<script>
import Header from "./Header";
import Footer from "./Footer";
import SiderMenu from "./SiderMenu";
export default {
name: "",
components: {
Header,
Footer,
SiderMenu
}
};
</script>
<style scoped></style>
我們隨便在這三個組件裏放上文字,如Header組件中放上頭部,SiderMenu組件中放入側邊欄,運行npm run serve,可以看到如下效果
二 引入nprogess來展示路由跳轉效果
1.下載: 運行npm i nprogess
2. 引入 在router/index.js中加上如下代碼進行引入
import NProgress from "nprogress";
import "nprogress/nprogress.css";
3. 添加路由守衛,在路由跳轉前開啓nprogess,路由跳轉結束後停止
//路由跳轉前
router.beforeEach((before, to, next) => {
NProgress.start();
next();
});
//路由跳轉後,停止
router.afterEach(() => {
NProgress.done();
});
4. 測試,我們在App.vue中加入一個路由鏈接,跳轉到分析頁
<router-link to="/dashboard/analysis">分析頁</router-link>
這樣,我們在點擊的時候就會有加載效果了.
三 實現BasicLayout樣式
下圖是Ant Design Pro of React網站的樣子
我們去Ant Design Vue官網(https://www.antdv.com/)的Layout裏去找 類似的樣式,下圖就是相類似的樣式
現在我們複製其代碼到我們的BasicLayout裏,相應的Header、SiderMenu和Footer部分用我們的組件替代,代碼如下
<template>
<div>
<a-layout id="components-layout-demo-side" style="min-height: 100vh">
<a-layout-sider collapsible v-model="collapsed">
<div class="logo"></div>
<SiderMenu></SiderMenu>
</a-layout-sider>
<a-layout>
<a-layout-header style="background: #fff; padding: 0" >
<Header></Header>
</a-layout-header>
<a-layout-content style="margin: 0 16px">
<router-view></router-view>
</a-layout-content>
<a-layout-footer style="text-align: center">
<Footer></Footer>
</a-layout-footer>
</a-layout>
</a-layout>
</div>
</template>
<script>
import Header from "./Header";
import Footer from "./Footer";
import SiderMenu from "./SiderMenu";
export default {
name: "",
components: {
Header,
Footer,
SiderMenu
},
data() {
return {
collapsed: false,//控制左側菜單伸縮
};
},
};
</script>
<style scoped></style>
現在我們還不能看到效果,因爲我們未引入Layout組件,在main.js裏進行引入
import { Button, Layout } from "ant-design-vue";
Vue.use(Layout);
最後運行npm run serve就可以看到效果如下
我們按下面的"<"就會收縮側邊欄,現在我們想向上面的樣式一樣點擊上面的圖標進行收縮,因此我們先將"<"隱藏,按照官方說明,我們在<a-layout-sider>添加:trigger="null"即可,可以發現"<"不見了,然後在<a-layout-header>裏添加icon圖標
<a-icon @click="collapsed=!collapsed" style="margin-left: 20px" :type="collapsed? 'menu-fold':'menu-unfold'"></a-icon>
最後引入Icon組件,運行npm run serve,可以看到如下效果,可以靠這個圖標控制收縮
至於頭部的東西到下面去了,我們只需加上float:right即可
就此,我們就實現了第一步。