文章目录
前言
承接上篇,本篇继续实现登录业务。上篇已经实现了后端业务,本篇主要实现前端业务,然后简单介绍一下前端的调试方法。
一、前端代码
1.修改utils/request.js文件
修改utils下request.js文件,增加前端请求和回复拦截器,前端请求时带上token,前端收到回复时有错误输出提示。
import {useTokenStore} from '@/stores/token.js'
//添加请求拦截器
instance.interceptors.request.use(
(config)=>{
//请求前的回调
//添加token
const tokenStore = useTokenStore();
//判断有没有token
if(tokenStore.token){
config.headers.Authorization = tokenStore.token
}
return config;
},
(err)=>{
//请求错误的回调
Promise.reject(err)
}
)
/* import {useRouter} from 'vue-router'
const router = useRouter(); */
import router from '@/router'
//添加响应拦截器
instance.interceptors.response.use(
result => {
//判断业务状态码
if(result.data.code===0){
return result.data;
}
//操作失败
//alert(result.data.msg?result.data.msg:'服务异常')
ElMessage.error(result.data.msg?result.data.msg:'服务异常')
//异步操作的状态转换为失败
return Promise.reject(result.data)
},
err => {
//判断响应状态码,如果为401,则证明未登录,提示请登录,并跳转到登录页面
if(err.response.status===401){
ElMessage.error('请先登录')
router.push('/login')
}else{
ElMessage.error('服务异常')
}
return Promise.reject(err);//异步的状态转化成失败的状态
}
)
2.修改api/user.js文件
修改api下user.js文件,增加userLoginService方法
//提供调用登录接口的函数
export const userLoginService = (loginData)=>{
const params = new URLSearchParams();
for(let key in loginData){
params.append(key,loginData[key])
}
return request.post('/user/login',params)
}
3.修改router/index.js
修改router下index.js文件,增加login路由。
//导入组件
import UserInfoVue from '@/views/UserInfo.vue'
import LoginVue from '@/views/UserLogin.vue'
//定义路由关系
const routes = [
{ path: '/', component: LoginVue },
{ path: '/user/userInfo', component: UserInfoVue },
]
4.增加stores/token.js
增加stores文件夹,里面增加token.js文件,pinia插件主要是前端保存数据使用,这里使用pinia插件保存token。
//定义store
import {defineStore} from 'pinia'
import {ref} from 'vue'
/*
第一个参数:名字,唯一性
第二个参数:函数,函数的内部可以定义状态的所有内容
返回值: 函数
*/
export const useTokenStore = defineStore('token',()=>{
//定义状态的内容
//1.响应式变量
const token = ref('')
//2.定义一个函数,修改token的值
const setToken = (newToken)=>{
token.value = newToken
}
//3.函数,移除token的值
const removeToken = ()=>{
token.value=''
}
return {
token,setToken,removeToken
}
},{
persist:true//持久化存储
});
5.增加views/Login.vue
views下增加Login.vue文件实现登录页面。element-plus插件主要实现界面呈现。
<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
//定义数据模型
const registerData = ref({
username: '',
password: '',
})
//记住用户名和密码
const rememberMe = ref(false)
//定义表单校验规则
const rules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 5, max: 16, message: '长度为5~16位非空字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 5, max: 16, message: '长度为5~16位非空字符', trigger: 'blur' }
]
}
//绑定数据,复用注册表单的数据模型
//表单数据校验
//登录函数
import {useTokenStore} from '@/stores/token.js'
import {useRouter} from 'vue-router'
const router = useRouter()
const tokenStore = useTokenStore();
import { userLoginService} from '@/api/user.js'
const login =async ()=>{
console.log("11" + registerData.value.username + "22" + registerData.value.password);
//调用接口,完成登录
let result = await userLoginService(registerData.value);
/* if(result.code===0){
alert(result.msg? result.msg : '登录成功')
}else{
alert('登录失败')
} */
//alert(result.msg? result.msg : '登录成功')
ElMessage.success(result.msg ? result.msg : '登录成功')
//把得到的token存储到pinia中
tokenStore.setToken(result.data)
//跳转到首页 路由完成跳转
router.push('/user/userInfo')
}
</script>
<template>
<el-row class="login-page">
<el-col :span="12" class="bg"></el-col>
<el-col :span="6" :offset="3" class="form">
<!-- 登录表单 -->
<el-form ref="form" size="large" autocomplete="off" :model="registerData" :rules="rules">
<el-form-item>
<h1>登录</h1>
</el-form-item>
<el-form-item label="账户" prop="username">
<el-input :prefix-icon="User" placeholder="请输入用户名" v-model="registerData.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input name="password" :prefix-icon="Lock" type="password" placeholder="请输入密码" v-model="registerData.password"></el-input>
</el-form-item>
<el-form-item class="flex">
<div class="flex">
<el-checkbox v-model="rememberMe">记住我</el-checkbox>
</div>
</el-form-item>
<!-- 登录按钮 -->
<el-form-item>
<el-button class="button" type="primary" auto-insert-space @click="login">登录</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
6.修改main.js
修改main.js,增加pinia的两个插件
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import router from '@/router'
import App from './App.vue'
import {createPinia} from 'pinia'
import { createPersistedState } from 'pinia-persistedstate-plugin'
import locale from 'element-plus/dist/locale/zh-cn.js'
const app = createApp(App);
const pinia = createPinia();
const persist = createPersistedState();
pinia.use(persist)
app.use(pinia)
app.use(router)
app.use(ElementPlus,{locale});
app.mount('#app')
7.修改vue.config.js文件
vue.config.js文件修改如下:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
devServer: {
client: {
overlay: false,
},
},
transpileDependencies: true
})
二、调试方法
1.浏览器检查
右键点击浏览器页面,选择“检查”菜单。
出现以下界面,选择“控制台”,然后操作界面如果出错这里会有提示。下图提示表示由于跨域原因无法访问后端,原因有二:
1、后端controller类没有加跨域注解,可以为每个controller类增加跨域注解,或者使用WebMvcConfigurer类增加addCorsMappings方法,详见上篇。
2、如果后端已经加了跨域注解仍然出现该错误,那应该是后端增加了interceptors,但是拦截器拦截了预检请求(preflight request),预检请求是一种由浏览器自动发送的、使用OPTIONS方法的HTTP请求,它用于检查实际请求是否可以被服务器接受。在preHandle方法中增加处理OPTIONS请求时,返回正确的CORS头部信息,详见上篇。
2.console打印
可以在js或者vue文件增加console.log打印日志,运行后会在检查–控制台中输出打印信息。
三、测试验证
分别运行后端代码和前端代码,可以在浏览器测试验证。登录页面如下:
登录成功后可以查询用户信息。
总结
这两篇主要是实现B/S架构的典型应用登录,下一篇我们将研究把以上应用打包部署到一个docker容器中。