【全栈】SprintBoot+vue3迷你商城(7)
【全栈】SprintBoot+vue3迷你商城(7)
往期的文章都在这里啦,大家有兴趣可以看一下
后端部分:
【全栈】SprintBoot+vue3迷你商城(1)
【全栈】SprintBoot+vue3迷你商城(2)
【全栈】SprintBoot+vue3迷你商城-扩展:利用python爬虫爬取商品数据
【全栈】SprintBoot+vue3迷你商城(3)
【全栈】SprintBoot+vue3迷你商城(4)
【全栈】SprintBoot+vue3迷你商城(5)
【全栈】SprintBoot+vue3迷你商城(6)
前端部分:
【全栈】SprintBoot+vue3迷你商城-扩展:vue的基本用法
【全栈】SprintBoot+vue3迷你商城-扩展:vue3项目创建及目录介绍
本期我们开始迷你商城前端的开发
文章目录
- 【全栈】SprintBoot+vue3迷你商城(7)
- 1.安装所需依赖
- 1.1.Element-Plus
- 1.2.Axios
- 1.3.Sass
- 2.开发基本步骤
- 3.登录、注册页面的开发
- 3.1.搭建页面,绑定数据与函数
- 3.2.制定与后端接口交互的函数
- 3.3.制定统一请求入口以及请求、响应拦截器:
- 3.4.解决跨域问题:
- 4.效果展示
- 5.总结
1.安装所需依赖
1.1.Element-Plus
npm install element-plus --save
1.2.Axios
npm install axios
1.3.Sass
npm install sass -D
2.开发基本步骤
- 首先需要搭建页面
- 然后为页面绑定数据模型及事件
- 之后再调用后端的接口
3.登录、注册页面的开发
3.1.搭建页面,绑定数据与函数
/src/views/Login.vue
<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref } from 'vue'
import { useRouter } from 'vue-router';
import { useTokenStore } from '@/stores/token'
import { ElMessage } from 'element-plus';
const router = useRouter();
const isRegister = ref(false)
const registerData = ref({
username: '',
userType: '',
password: '',
rePassword: ''
})
const clearRegisterData = () => {
registerData.value = {
username: '',
password: '',
rePassword: ''
}
}
import { userLoginService, userRegisterService } from "@/api/user"
const login = async () => {
let result = await userLoginService(registerData.value)
ElMessage.success(result.msg ? result.msg : '登录成功');
const tokenStore = useTokenStore()
tokenStore.setToken(result.data)
router.push('/')
}
const register = async () => {
let result = await userRegisterService(registerData.value)
ElMessage.success(result.msg ? result.msg : '注册成功');
clearRegisterData();
ElMessage.success('请登录')
}
const options= ref([
'普通用户',
'商家'
])
</script>
<template>
<el-row class="login-page" style="background-color:lightpink;">
<el-col :span="12" class="bg"></el-col>
<el-col :span="6" :offset="3" class="form">
<el-form ref="form" size="large" autocomplete="off" v-if="isRegister">
<el-form-item>
<h1>注册</h1>
</el-form-item>
<el-form-item>
<el-input :prefix-icon="User" placeholder="请输入用户名" v-model="registerData.username"></el-input>
</el-form-item>
<el-select placeholder="请选择用户类型" size="large" style="width: 208px;margin-bottom: 20px;" v-model="registerData.userType" >
<el-option v-for="item in options" :key="item" :value="item" />
</el-select>
<el-form-item>
<el-input :prefix-icon="Lock" type="password" placeholder="请输入密码"
v-model="registerData.password"></el-input>
</el-form-item>
<el-form-item>
<el-input :prefix-icon="Lock" type="password" placeholder="请输入再次密码"
v-model="registerData.rePassword"></el-input>
</el-form-item>
<el-form-item>
<el-button class="button" type="danger" @click="register()" auto-insert-space>
注册
</el-button>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="isRegister = false; clearRegisterData()"
style="color: coral;">
返回
</el-link>
</el-form-item>
</el-form>
<el-form ref="form" size="large" autocomplete="off" v-else>
<el-form-item>
<h1>登录</h1>
</el-form-item>
<el-form-item>
<el-input :prefix-icon="User" placeholder="请输入用户名" v-model="registerData.username"></el-input>
</el-form-item>
<el-form-item>
<el-input name="password" :prefix-icon="Lock" type="password" placeholder="请输入密码"
v-model="registerData.password"></el-input>
</el-form-item>
<el-form-item>
<el-button class="button" type="danger" auto-insert-space @click="login()">登录</el-button>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="isRegister = true; clearRegisterData()"
style="color: coral;">
注册
</el-link>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
<style lang="scss" scoped>
.login-page {
height: 100vh;
background: url('@/assets/logo2.jpg') no-repeat 88% 0% / 500px auto;
.bg {
background:
url('@/assets/login_bg.jpg') no-repeat center / cover;
border-radius: 0 20px 20px 0;
}
.form {
display: flex;
flex-direction: column;
justify-content: center;
user-select: none;
.title {
margin: 0 auto;
}
.button {
width: 100%;
}
.flex {
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
</style>
3.2.制定与后端接口交互的函数
/src/api/user.js
import request from '@/utils/request'
export const userRegisterService =(registerData)=>{
const params =new URLSearchParams();
for(let key in registerData){
params.append(key ,registerData[key]);
}
return request.post('/user/register',params);
}
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.3.制定统一请求入口以及请求、响应拦截器:
/src/utils/request.js
import axios from 'axios';
import {useTokenStore} from '@/stores/token'
import { ElMessage } from 'element-plus';
const baseURL = '/api';
const instance = axios.create({baseURL})
instance.interceptors.request.use(
(config)=>{
const tokenStore=useTokenStore();
if (tokenStore.token){
config.headers.Authorization=tokenStore.token
}
return config
},
(err)=>{
Promise.reject(err);
}
)
import router from '@/router';
//响应拦截器
instance.interceptors.response.use(
result=>{
if(result.data.code===0){
return result.data;
}
ElMessage.error(result.data.msg?result.data.msg:'服务异常')
return Promise.reject(result.data)
},
err=>{
if (err.response.status===401){
ElMessage.error('请先登录')
router.push('/login')
}else{
ElMessage.error('服务异常')
}
return Promise.reject(err);
}
)
export default instance;
3.4.解决跨域问题:
vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
server:{
proxy:{
'/api':{
target:'http://localhost:8080',
changeOrigin:true,
rewrite:(path)=>path.replace(/^\/api/,'')
}
}
}
})
如果有不懂的地方可以看【全栈】SprintBoot+vue3迷你商城-扩展:vue3项目创建及目录介绍
然后再结合这里面的代码示例
4.效果展示
初次尝试,页面制作的较为粗糙,请见谅
5.总结
本期我们进行了登录、注册页面的搭建以及接口绑定,下期我们将介绍登录后跳转的主页面的开发。