基于Vue2.x的前端架构,我们是这么做的
Posted 街角小林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Vue2.x的前端架构,我们是这么做的相关的知识,希望对你有一定的参考价值。
通过Vue CLI
可以方便的创建一个Vue
项目,但是对于实际项目来说还是不够的,所以一般都会根据业务的情况来在其基础上添加一些共性能力,减少创建新项目时的一些重复操作,本着学习和分享的目的,本文会介绍一下我们Vue
项目的前端架构设计,当然,有些地方可能不是最好的方式,毕竟大家的业务不尽相同,适合你的就是最好的。
除了介绍基本的架构设计,本文还会介绍如何开发一个Vue CLI
插件和preset
预设。
ps.本文基于Vue2.x版本,node版本16.5.0
复制代码
创建一个基本项目
先使用Vue CLI
创建一个基本的项目:
vue create hello-world
复制代码
然后选择Vue2
选项创建,初始项目结构如下:
接下来就在此基础上添砖加瓦。
路由
路由是必不可少的,安装vue-router
:
npm install vue-router
复制代码
修改App.vue
文件:
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default
name: App,
</script>
<style>
*
padding: 0;
margin: 0;
border: 0;
outline: none;
html,
body
width: 100%;
height: 100%;
</style>
<style scoped>
#app
width: 100%;
height: 100%;
display: flex;
</style>
复制代码
增加路由出口,简单设置了一下页面样式。
接下来新增pages
目录用于放置页面, 把原本App.vue
的内容移到了Hello.vue
:
路由配置我们选择基于文件进行配置,在src
目录下新建一个/src/router.config.js
:
export default [
path: /,
redirect: /hello,
,
name: hello,
path: /hello/,
component: Hello,
]
复制代码
属性支持vue-router
构建选项routes的所有属性,component
属性传的是pages
目录下的组件路径,规定路由组件只能放到pages
目录下,然后新建一个/src/router.js
文件:
import Vue from vue
import Router from vue-router
import routes from ./router.config.js
Vue.use(Router)
const createRoute = (routes) =>
if (!routes)
return []
return routes.map((item) =>
return
...item,
component: () =>
return import(./pages/ + item.component)
,
children: createRoute(item.children)
)
const router = new Router(
mode: history,
routes: createRoute(routes),
)
export default router
复制代码
使用工厂函数和import
方法来定义动态组件,需要递归对子路由进行处理。最后,在main.js
里面引入路由:
// main.js
// ...
import router from ./router// ++
// ...
new Vue(
router,// ++
render: h => h(App),
).$mount(#app)
复制代码
菜单
我们的业务基本上都需要一个菜单,默认显示在页面左侧,我们有内部的组件库,但没有对外开源,所以本文就使用Element
替代,菜单也通过文件来配置,新建/src/nav.config.js
文件:
export default [
title: hello,
router: /hello,
icon: el-icon-menu
]
复制代码
然后修改App.vue
文件:
<template>
<div id="app">
<el-menu
style="width: 250px; height: 100%"
:router="true"
:default-active="defaultActive"
>
<el-menu-item
v-for="(item, index) in navList"
:key="index"
:index="item.router"
>
<i :class="item.icon"></i>
<span slot="title"> item.title </span>
</el-menu-item>
</el-menu>
<router-view />
</div>
</template>
<script>
import navList from ./nav.config.js
export default
name: App,
data()
return
navList,
,
computed:
defaultActive()
let path = this.$route.path
// 检查是否有完全匹配的
let fullMatch = navList.find((item) =>
return item.router === path
)
// 没有则检查是否有部分匹配
if (!fullMatch)
fullMatch = navList.find((item) =>
return new RegExp(^ + item.router + /).test(path)
)
return fullMatch ? fullMatch.router :
,
,
</script>
复制代码
效果如下:
当然,上述只是意思一下,实际的要复杂一些,毕竟这里连嵌套菜单的情况都没考虑。
权限
我们的权限颗粒度比较大,只控制到路由层面,具体实现就是在菜单配置和路由配置里的每一项都新增一个code
字段,然后通过请求获取当前用户有权限的code
,没有权限的菜单默认不显示,访问没有权限的路由会重定向到403
页面。
获取权限数据
权限数据随用户信息接口一起返回,然后存储到vuex
里,所以先配置一下vuex
,安装:
npm install vuex --save
复制代码
新增/src/store.js
:
import Vue from vue
import Vuex from vuex
Vue.use(Vuex)
export default new Vuex.Store(
state:
userInfo: null,
,
actions:
// 请求用户信息
async getUserInfo(ctx)
let userInfo =
// ...
code: [001] // 用户拥有的权限
ctx.commit(setUserInfo, userInfo)
,
mutations:
setUserInfo(state, userInfo)
state.userInfo = userInfo
,
)
复制代码
在main.js
里面先获取用户信息,然后再初始化Vue
:
// ...
import store from ./store
// ...
const initApp = async () =>
await store.dispatch(getUserInfo)
new Vue(
router,
store,
render: h => h(App),
).$mount(#app)
initApp()
复制代码
菜单
修改nav.config.js
新增code
字段:
// nav.config.js
export default [
title: hello,
router: /hello,
icon: el-icon-menu
code: 001,
]
复制代码
然后在App.vue
里过滤掉没有权限的菜单:
export default
name: App,
data()
return
navList,// --
,
computed:
navList() // ++
const userInfo = this.$store.state
if (!userInfo || !userInfo.code || userInfo.code.length <= 0) return []
return navList.filter((item) =>
return userInfo.code.includes(item.code)
)
复制代码
这样没有权限的菜单就不会显示出来。
路由
修改router.config.js
,增加code
字段:
export default [
path: /,
redirect: /hello,
,
name: hello,
path: /hello/,
component: Hello,
code: 001,
]
复制代码
code
是自定义字段,需要保存到路由记录的meta
字段里,否则最后会丢失,修改createRoute
方法:
// router.js
// ...
const createRoute = (routes) =>
// ...
return routes.map((item) =>
return
...item,
component: () =>
return import(./pages/ + item.component)
,
children: createRoute(item.children),
meta: // ++
code: item.code
)
// ...
复制代码
然后需要拦截路由跳转,判断是否有权限,没有权限就转到403
页面:
// router.js
// ...
import store from ./store
// ...
router.beforeEach((to, from, next) =>
const userInfo = store.state.userInfo
const code = userInfo && userInfo.code && userInfo.code.length > 0 ? userInfo.code : []
// 去错误页面直接跳转即可,否则会引起死循环
if (/^\\/error\\//.test(to.path))
return next()
// 有权限直接跳转
if (code.includes(to.meta.code))
next()
else if (to.meta.code) // 路由存在,没有权限,跳转到403页面
next(
path: /error/403
)
else // 没有code则代表是非法路径,跳转到404页面
next(
path: /error/404
)
)
复制代码
error
组件还没有,新增一下:
// pages/Error.vue
<template>
<div class="container"> errorText </div>
</template>
<script>
const map =
403: 无权限,
404: 页面不存在,
export default
name: Error,
computed:
errorText()
return map[this.$route.params.type] || 未知错误
,
,
</script>
<style scoped>
vue2.X项目架构搭建基于vueCli+webPack 创建项目使用vue2.x+webpack+vuex+sass+axios+elementUI等快速搭建前端项目框架
微服务架构SpringBoot+SpringCloud+VUE二 || 项目架构简介