该项目使用了路由前置守卫,手动配置路由。
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/login' // 引入路由组件
import Layout from '@/views/layout'
import Dashboard from '@/views/dashboard'
import Article from '@/views/article'
import store from '@/store' // 引入vuex里的状态的token(查看是否有token)
Vue.use(VueRouter)
const router = new VueRouter({
routes: [ // 路由配置
{ path: '/login', component: Login }, // 一级登录页
{
path: '/', // 首页
component: Layout,
redirect: '/dashboard', // 重定向。到子路由的登录页面
children: [
{ path: '/dashboard', component: Dashboard },
{ path: '/article', component: Article }
]
}
]
})
const whiteList = ['/login'] // 白名单(没有登录可以访问的页面,如:登录页,注册页)
router.beforeEach((to, from, next) => { // 封装登录的前置路由守卫(判断token)
const token = store.state.user.token// 先获取vuex仓库里状态里的token
if (token) { // 如果token存在
next() // 就放行
return // 下面的代码就都不执行了
}
if (whiteList.includes(to.path)) { // 看要去的to路径是否在白名单里
next()// 如果是去白名单登录页的话直接放行
return
}
next('/login') // 其他情况拦截到登录页
})
export default router
<template>
<div class="login-page">
<el-card class="login-card">
<template #header>登录页</template>
<el-form :model="form" :rules="rules" ref="from">
<el-form-item label="用户名:" prop="username">
<el-input placeholder="请输入用户名" v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input placeholder="请输入密码" type="password" v-model="form.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login('ruleForm')">登录</el-button>
<el-button @click="reset('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
name: 'LoginIndex',
data () {
return {
form: { // 嵌套在from里方便管理
username: '',
password: ''
},
rules: { // 校验from里输入的信息
username: [ // 校验用户名输入框规则
{ required: true, message: '提示输入错误', trigger: ['blur', 'change'] }
// required非空校验 trigger触发校验时机blur是失焦时,change内容框被修改时触发
],
password: [
{ required: true, message: '提示输入错误', trigger: ['blur', 'change'] },
{ pattern: /^\w{5,11}$/, message: '密码长度在5-11位', trigger: 'blur' }
]
}
}
},
methods: {
async login () { // 登录功能
try {
await this.$refs.from.validate()
await this.$store.dispatch('user/loginAction', this.form)// 调用vuex里的actions异步操作(发送登录请求)
this.$message.success('弹框登录成功')
this.$router.push('/') // 登录成功并且跳转首页(路由跳转)
console.log('通过校验,准备发请求')
} catch (e) {
console.log('错误', e)
}
},
reset () { // 重置逻辑
}
}
}
</script>
<style lang="scss" scoped>
.login-page {
min-height: 100vh;
background: url(@/assets/login-bg.svg) no-repeat center / cover;
display: flex;
align-items: center;
justify-content: space-around;
.el-card {
width: 420px;
::v-deep .el-card__header{
height: 80px;
background: rgba(114,124,245,1);
text-align: center;
line-height: 40px;
color: #fff;
font-size: 18px;
}
}
.el-form {
padding: 0 20px;
}
.tc {
text-align: center;
}
}
</style>
封装用户相关的模块,新建api文件用于单独储存
import { login } from '@/api/user' // 封装api请求登录函数名login
import { getToken, setToken } from '@/utils/storage' // 把封装好的token获取,设置方法引入
export default {
namespaced: true,
state () { // vuex状态,用来提供数据的
return {
token: getToken() || '', // 初始token数据.先出本地存储里获取,本地没有值才为空(在vuex里)
words: '测试文本'
}
},
mutations: { // vuex提供操作数据方法
setUserToken (state, newToken) {
state.token = newToken // 把token更新,存放在vuex里
setToken(newToken)// 把新获取的token放到本地存储里一份
}
},
actions: { // 提供异步操作的
async loginAction (context, obj) { // 发送登录请求(拿到上下文,from对象).往vuex里存取token
const res = await login(obj) // 调用封装的登录请求接口
console.log(res.data.token)
context.commit('setUserToken', res.data.token)// context.commit 是用于触发 mutations 的方法('接收封装好的函数名',把获取的新token传值)
}
}
}
还有更多项目案例,欢迎和我联系