前言
为了调试Auth后端,写了一个Vue的前端,结合以前写的文章,对Vue为代表的前端做一个总结,内容分为:
- Control
- View与Data
- Element组件
- CSS
本文是Control部分,这里是整个工程的结构,包括router、Layout、Navigation、interceptor等内容。
Router
整个前端框架是通过router结合在一起的,在router中注册各种路由(route),当访问这些路由时,引向相应的页面。Router是整个前端的控制核心。
在router的使用上,简单情况下,可以是固定的routes,但更多情况下是动态的routes,可以根据角色、权限的不同来显示不同的页面。
- 首先声明asyncRoutes路由,并设置该路由所需要的权限
- 然后在store中存储用户拥有的权限
- 接着在router的拦截器(beforeEach)中进行对比,通过router.addRoutes()将复合的route注册进router。对比的结果也可以放到store中。
- 最后还需要根据这些动态的route生成相应的Navigation。
Layout
Layout是Router的一部分,它是所有(或一部分)页面的共同的部分。
代码如下:
const routes: Array<RouteRecordRaw> = [
{
path: "/",
redirect: "/dashboard",
},
{
path: "/",
name: "Layout",
component: Layout,
children: [
{
path: "/dashboard",
name: "Dashboard",
meta: {
title: "首页",
},
component: () => import("../views/Dashboard.vue"),
},
{
path: "/org",
name: "Org",
meta: {
title: "组织管理",
},
component: () => import("../views/Org.vue"),
}
//... More...
]
}
这里通过在父route上加componet的形式,使子route继承了这些公共的组件。
当然,这些公共组件也需要对嵌入其中的子compont留出空间,通过route-view来嵌入相应子组件,示例:
<template>
<Header></Header>
<Sidebar></Sidebar>
<div class="content-box" :class="{'content-collapse': isCollapse}">
<router-view v-slot="{ Component }">
<transition name="move" mode="out-in">
<keep-alive>
<component :is="Component"></component>
</keep-alive>
</transition>
</router-view>
</div>
</template>
公共的组件可以包括但不限于:header、sidebar(Navigation)、breadcrumb等等内容
Navigation
Navigation是一个网站很重要的一个方面,从位置上,可以是侧栏导航,也可以是顶部导航;从层级上有1层、2层、3层多种形式, 可以参考element-plus导航建议。
导航渲染的就是route注册的路由,这样对于动态的route,从store中获取它们会更方便一些。示例:
<template>
<div class="sidebar">
<el-menu class="sidebar-el-menu" :default-active="onRoutes" :collapse="isCollapse" router>
<template v-for="item in routes">
<template v-if="!item.subs">
<el-menu-item :index="item.index" :key="item.index">
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<template #title>{{ item.title }}</template>
</el-menu-item>
</template>
<template v-else>
<el-sub-menu :index="item.index" :key="item.index">
<template #title>
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs" :key="subItem.index">
<el-menu-item :index="subItem.index">
{{ subItem.title }}
</el-menu-item>
</template>
</el-sub-menu>
</template>
</template>
</el-menu>
</div>
</template>
Interceptor
router的拦截
每个内部跳转时,都进行调用
router.beforeEach((to, from, next) => {
// ...
})
router.afterEach((to, from) => {
// ...
})
这个next是一个导航,确保 next
函数在任何给定的导航守卫中都被严格调用一次。
以上为全局的,每个路由还有可以有。
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
axios的拦截
axios的拦截是通过service.interceptors.request
与service.interceptors.response
来完成的,在访问前的request拦截中,可以增加公共的Header,在返回的response拦截中,可以结果,尤其是错误进行相应的处理。
service.interceptors.request.use(
(config) => {
// 这里可以对request的header加点料
return config;
},
(error) => {
console.log(error);
return Promise.reject();
}
);
service.interceptors.response.use(
(response: AxiosResponse<any>) => {
const { data, config } = response;
if (response.status === 200) {
// 正确放回的处理...
} else {
Promise.reject();
}
},
(error) => {
const { response, message } = error;
// 错误返回的处理...
);
总结
前端控制的核心是Router,通过Router组织全部的页面。Router中配置公共的Layout,一个重要的Layout就是Navigation。与后端类似,这里也有拦截器,最常用的是Router渲染时的拦截,以及axios访问后端的拦截。