目录
1.创建表单
<template>
<div class="login-container">
<el-form
class="login-form"
ref="loginFormRef"
:model="loginForm"
:rules="loginRules"
>
<div class="title-container">
<h3 class="title">用户登陆</h3>
</div>
<!-- mobile -->
<el-form-item prop="mobile">
<span class="svg-container">
<svg-icon icon="user"></svg-icon>
</span>
<el-input
placeholder="mobile"
name="mobile"
type="text"
v-model="loginForm.mobile"
></el-input>
</el-form-item>
<!-- password -->
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon="password"></svg-icon>
</span>
<el-input
placeholder="password"
name="password"
:type="passwordType"
v-model="loginForm.password"
></el-input>
<span class="show-pwd">
<span class="svg-container" @click="onChangePwdType">
<svg-icon
:icon="passwordType === 'password' ? 'eye' : 'eye-open'"
></svg-icon>
</span>
</span>
</el-form-item>
<!-- 登陆按钮 -->
<el-button
type="primary"
style="width: 100%; margin-bottom: 30px"
:loading="loading"
@click="handlerLogin"
>
登陆
</el-button>
</el-form>
</div>
</template>
2.表单验证
/**
* 校验手机号 /utils/validate
* ***/
export function validMobile(str) {
return /^1[3-9]\d{9}$/.test(str)
}
import { validMobile } from '@/utils/validate'
export default {
data() {
const validateMobile = (rule, value, callback) => {
validMobile(value) ? callback() : callback(new Error('手机号格式不正确'))
}
return {
loginForm: {
mobile: '13800000002',
password: '123456'
},
loginRules: {
// trigger 校验的触发方式 blur/change
// 自定义函数
mobile: [{ required: true, trigger: 'blur', message: '手机号不能为空' }, {
validator: validateMobile, trigger: 'blur'
}],
password: [{ required: true, trigger: 'blur', message: '密码不能为空' }, {
trigger: 'blur', min: 6, max: 16, message: '密码长度为6-16位之间'
}]
},
loading: false,
}
},
3.登录请求
/** *
* 登陆接口封装 /api/user
* **/
export function login(data) {
// 返回一个promise对象
return request({
url: '/xxxxxx',
method: 'post',
data
})
}
//utils/auth
import Cookies from 'js-cookie'
export function getToken() {
return Cookies.get(TokenKey)
}
import { getToken} from '@/utils/auth'
import { login } from '@/api/user'
// 状态
const state = {
token: getToken(), // 设置token为共享状态 初始化vuex的时候 就先从缓存中读取
userInfo: {} // 这里定义一个空对象 为什么要定义空对象
}
const mutations = {
setToken(state, token) {
state.token = token // 将数据设置给vuex
// 同步给缓存
setToken(token)
}
}
const actions = {
async login(context, data) {
// 调用api接口
const result = await login(data) // 拿到token
context.commit('setToken', result) // 设置token
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
4.封装登录请求动作
methods: {
...mapActions(['user/login']), // 引入方法
handleLogin() {
// 表单的手动校验
this.$refs.loginForm.validate(async isOK => {
if (isOK) {
try {
this.loading = true
// 只有校验通过了 我们才去调用action
await this['user/login'](this.loginForm)
// 应该登录成功之后
// async标记的函数实际上一个promise对象
// await下面的代码 都是成功执行的代码
this.$router.push('/')
} catch (error) {
console.log(error)
} finally {
// 不论执行try 还是catch 都去关闭转圈
this.loading = false
}
}
})
}
}
}
5.创建响应拦截器
import axios from 'axios'
import { ElMessage } from 'element-plus'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
// 响应拦截器
service.interceptors.response.use(
// 请求成功
(response) => {
const data = response.data
// 需要判断当前请求是否成功
if (data != null) {
// 成功返回解析后的数据
const message1 = '-登陆成功-'
ElMessage.success(message1)
return data
} else {
// 失败(请求成功,业务失败) 消息提示
const message1 = '-请求成功,业务失败-'
ElMessage.error(message1)
return Promise.reject(new Error(message1))
}
},
// 请求失败
(error) => {
const message2 = '-请求失败-'
ElMessage.error(message2)
return Promise.reject(error)
}
)
export default service
6.登录权限
import { createRouter, createWebHashHistory } from 'vue-router'
const Routes = [
{
path: '/login',
component: () => import('@/views/login/index')
},
{
path: '/',
component: () => import('@/layout/index')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: Routes
})
export default router
7.导航守卫
import router from '@/router'
import store from '@/store'
// 白名单
const whileList = ['/login']
router.beforeEach((to, from, next) => {
if (store.getters.token) {
if (to.path === '/login') {
next('/')
} else {
next()
}
} else {
if (whileList.indexOf(to.path) > -1) {
next()
} else {
next('/login')
}
}
})