手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)
基于这篇文章的学习,开始动手写了一个简易的vue管理后台。vue
views:各业务组件
components:公共组件(面包屑,导航开关等等)
api: 请求的js文件
icons: svg和相关配置文件(此项目的图标是使用svg-sprite-loader来实现的, 以前写过的相关文章连接
permission.js 检查权限
其余地方与别的项目结构一致,我就再也不赘述了。ios
接下来我会以 实现页面的结构、面包屑导航、左侧树形导航、页面跳转这四个基础模块去讲解。由于篇幅有限,在这篇文章只放功能相关的部分代码,github源码连接在文章最后。git
(由于除了login等特殊页面外,其余的结构都是一致的。因此能够用Layout组件来承载页面的结构)
@/views/Layout/的目录结构以下github
对应到Layout的各个区域以下图。ajax
当点击切换路由时,sidebar和navbar不会改变,只有app-main组件的内容会改变。
实现思路:左侧导航栏的路由的component为Layout,再经过router的redirect属性控制显示app-main区域的路由。部分代码以下vue-router
@/Layout/Layout.vuevue-cli
<template> <div class="app-wrapper" :class="classObj"> <!--导航 --> <sidebar/> <!--面包屑--> <div class="main-container"> <!-- 头部导航 --> <navbar/> <!-- 二级路由 --> <app-main/> </div> </div> </template> <script> import Sidebar from './components/Sidebar' import Navbar from './components/navbar' import AppMain from './components/AppMain' </script>
@/Layou/components/AppMain.vueelement-ui
<template> <section class="app-main"> <transition name="fade-transform" mode="out-in"> <!-- 在这里映射不一样的路由到Layout中的app-main --> <router-view/> </transition> </section> </template>
左侧的导航是经过element-ui的 el-menu组件和循环路由表来实现的。具体效果以下图axios
若是没有子路由,点击直接跳转。有则出现下拉弹框。segmentfault
使用element-ui里的el-breadcrumb组件,循环this.$router.matched数组渲染el-breadcrumb。
this.$router.matched数组包含当前路由的全部嵌套路径片断的路由记录(包括它的子路由)。
部分代码以下@/components/breadcrumb/index
<template> <el-breadcrumb class="app-breadcrumd" separator="/"> <transition-group name="breadcrumb"> <el-breadcrumb-item v-for="(item, index) in levelList" v-if="item.meta.title" :key="item.path"> <!--当前路由,点击不作跳转 --> <span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span> <a v-else @click.prevent="handleLink(item)">{{item.meta.title}}</a> </el-breadcrumb-item> </transition-group> </el-breadcrumb> </template>
该项目的处理逻辑为:
a.经过帐号密码请求登陆api获取token
b.将token保存到cookie和store中
c.经过判断token是否存在和导航守卫来控制路由
下面我将以上abc三个步骤分开来写
a:表单验证和发送请求
@/views/login/index 登陆页,表单使用elementui的el-form。
<!-- :rules 表单校验规则的对象 {username:[],password:[]}--> <!-- loginForm 整个表单须要提交的字段 {username:'',password:''} --> <el-form :rules="loginRules" :model="loginForm"> <!-- username是必填项 prop对应要验证的字段username --> <el-form-item prop="username"> <el-input v-model="loginForm.username" name="username" type="text" auto-complete="on" placeholder="username" /> </el-form-item> <!-- 密码 --> <el-form-item prop="password"> <el-input v-model="loginForm.username" type="password" name="password" auto-complete="on" /> </el-form-item> </el-form>
data() { //username的校验规则 const validateUsername = (rule, value, callback) => { // rule 对应的为loginRules.username的值 if (!isvalidUsername(value)) { callback(new Error('请输入正确的用户名')) } else { callback() } } // password的校验规则 const validatePass = (rule, value, callback) => { if (value.length < 5) { callback(new Error('密码不能小于5位')) } else { callback() } } return { // 表单校验规则 loginRules: { //required 是否必须 trigger 触发条件 validator 该字段的校验规则 username: [{required: true, trigger: 'blur', validator: validateUsername}], password: [{required: true, trigger: 'blur', validator: validatePass}] }, // 表单提交对象 loginForm: { username: } } }
发送请求
(由于没有后台的相关api,因此该项目的登陆、获取用户信息都是在 https://easy-mock.com/mock/59...。
该登陆接口下的帐号是 admin、editor。密码不能小于5位)
在开发环境下配置这个请求接口的域名
config/dev.env.js
module.exports = merge(prodEnv, { NODE_ENV: '"development"', BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"' //直接经过process.env.BASE_API 来获取 })
@/utils/request 封装ajax请求相关
@/api/login 封装登陆,获取用户信息相关的接口
b
请求成功获取token后保存到cookie和store中。这一步再也不仔细,详细代码在如下几个文件
处理token @/utils/auth
登陆 @/api/login
封装axios @/utils/request
C 经过判断token是否存在和导航守卫来控制路由
@/permission.js
处理逻辑:
(1)token存在,根据beforeRouter的to属性判断. 前往login,则经过next({path:'/'})改变to.path,由于不须要再登陆。 前往其余页面,先判断store里的roles数组是否为空(roles用来控制权限),若是为空则获取用户信息,再next()或者直接next() (2)token不存在,判断to.path是否存在白名单路由数组 存在,直接next() 不存在,前往login将to.path做为参数携带在url中,/login?redirect=${to.path}, 登陆成功后再跳转到to.path
若是喜欢请给个star吧!
https://github.com/lazyChan29...