首先创建一个使用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即可
就此,我们就实现了第一步。