基于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​​选项创建,初始项目结构如下:

基于Vue2.x的前端架构,我们是这么做的_前端

接下来就在此基础上添砖加瓦。

路由

路由是必不可少的,安装​​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​​:

基于Vue2.x的前端架构,我们是这么做的_多语言_02

路由配置我们选择基于文件进行配置,在​​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>
复制代码

效果如下:

基于Vue2.x的前端架构,我们是这么做的_前端_03

当然,上述只是意思一下,实际的要复杂一些,毕竟这里连嵌套菜单的情况都没考虑。

权限

我们的权限颗粒度比较大,只控制到路由层面,具体实现就是在菜单配置和路由配置里的每一项都新增一个​​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二 || 项目架构简介

Vue2.x源码学习笔记-Vue构造函数

前后端分离SpringBoot+SpringCloudAlibaba+VUE一 || 项目架构简介

前端面试(蚂蚁金服笔试)