第三天任务:与后端进行请求交互,在本地写入用户信息。
与后端进行请求交互
我们现在项目目录下面创建一个 .env.development 的配置文件。
然后我们在主目录下的 src 文件夹下新建三个文件夹,名称分别为 service、store、utils:service 里面用来写向后端发送的请求体; store 里面用来处理发送前后需要处理的事情,最常见的例如存储数据;utils 用来处理请求相关。创建如图示目录文件夹及文件:
下面开始写 request.js
import axios from 'axios';
import storageService from '@/service/storageService';
const service = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL,
timeout: 1000 * 5,
});
// Add a request interceptor
service.interceptors.request.use(function (config) {
// Do something before send request
Object.assign(config.headers, { Authorization: `Bearer ${storageService.get(storageService.USER_TOKEN)}` });
return config;
}, function (error) {
// deal with the request error
return Promise.reject(error);
});
export default service;
然后写 storageService ,这里选择把用户信息存到 vuex 当中,把 token 存在本地。
storageService.js
// local storage service
// your project prefix name as the storage prefix name
const PREFIX = 'Five Elements Six Gases';
// set user module
const USER_PREFIX = `${PREFIX}user_`;
const USER_TOKEN = `${USER_PREFIX}token`;
const USER_INFO = `${USER_PREFIX}info`;
// storage
const set = (key, data) => {
localStorage.setItem(key, data);
};
// get local storage info
const get = (key) => localStorage.getItem(key);
export default {
set,
get,
USER_INFO,
USER_TOKEN,
};
下面来写 userService.js 这里面主要是把数据封装进请求体中,例如 register 这里使用 formdata 表单封装数据。
import request from '@/utils/request';
// 用户注册
const register = ({ username, email, password }) => {
const formData = new FormData();
formData.append('UserName', username);
formData.append('UserEmail', email);
formData.append('UserPassword', password);
return request.post('auth/register', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
};
// 用户登录
const login = ({ username, password }) => {
const formData = new FormData();
formData.append('UserName', username);
formData.append('UserPassword', password);
return request.post('auth/login', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
};
// 用户编辑
const edit = ({ UserName, UserEmail, UserPassword, NewPassword }) => {
const formData = new FormData();
formData.append('UserName', UserName);
formData.append('UserEmail', UserEmail);
formData.append('UserPassword', UserPassword);
formData.append('NewPassword', NewPassword);
return request.put('auth/edit', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
// 获取用户信息
const info = (headers) => {
return request.get('auth/info', {
headers: headers,
});
};
export default {
register,
info,
login,
edit,
};
user.js 代码
import storageService from '@/service/storageService';
import userService from '@/service/userService';
const userModule = {
namespaced: true,
state: {
token: storageService.get(storageService.USER_TOKEN),
userInfo: null,
},
mutations: {
SET_TOKEN(state, token) {
// update local storage
storageService.set(storageService.USER_TOKEN, token);
// update state
state.token = token;
},
SET_USERINFO(state, userInfo) {
// update state
state.userInfo = userInfo;
},
},
actions: {
register(context, { username, email, password }) {
console.log("im register")
return new Promise((resolve, reject) => {
userService.register({ username, email, password }).then((res) => {
// save token
context.commit('SET_TOKEN', res.data.data.token);
return userService.info();
}).then((res) => {
// save user info
context.commit('SET_USERINFO', res.data.data.user);
resolve(res);
}).catch((err) => {
reject(err);
});
});
},
login(context, { username, password }) {
console.log("im login")
// console.log(username)
// console.log(password)
return new Promise((resolve, reject) => {
userService.login({ username, password }).then((res) => {
// 保存 token
context.commit('SET_TOKEN', res.data.data.token);
return userService.info();
}).then((res) => {
// 保存用户信息
context.commit('SET_USERINFO', res.data.data.user);
resolve(res);
}).catch((err) => {
reject(err);
});
});
},
logout({ commit }) {
// 清除 token
commit('SET_TOKEN', '');
storageService.set(storageService.USER_TOKEN, '')
window.location.reload();
},
edit(context, { UserName, UserEmail, UserPassword, NewPassword }) {
return new Promise((resolve, reject) => {
// console.log('userEdit method called');
// console.log(Response)
userService.edit({ UserName, UserEmail, UserPassword, NewPassword }).then((res) => {
// 清除 token
// context.commit('SET_TOKEN', '');
// storageService.set(storageService.USER_TOKEN, '');
// 清除用户信息
console.log(res)
context.commit('SET_USERINFO', '');
storageService.set(storageService.USER_INFO, '');
// // 保存 token
return userService.info();
// 保存用户信息
}).then((res) => {
context.commit('SET_USERINFO', res.data.data.user);
resolve(res);
}).catch((err) => {
context.commit('SET_TOKEN', '');
storageService.set(storageService.USER_TOKEN, '')
window.location.reload();
reject(err);
});
});
},
async getInfo(context, state) {
const { token } = state;
try {
const headers = {
// 在请求头中添加 token
Authorization: `Bearer ${token}`,
};
const response = await userService.info(headers);
context.commit('SET_USERINFO', response.data.data.user);
} catch (error) {
// 处理请求错误
console.error('Request failed:', error);
throw error;
}
}
},
};
export default userModule;
在写 index.js 之前我们需要先安装 vuex 和 axios。
我们在命令行当中输入
yarn add vuex@3
yarn add axios
index.js 代码
import Vue from 'vue';
import Vuex from 'vuex';
import UserModule from './module/user'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
UserModule,
},
});
当然到现在并没有完成,还记得之前的 login 和 register 点击的事件吗?没错,这个请求的发出当然和点击对应的事件相关联。
修改main.js代码:
import Vue from 'vue'
import App from './App.vue'
import router from './router';
import axios from 'axios';
import store from './store';
import { Button, Menu, Input, MenuItem, Form, FormItem, Submenu, MessageBox, Message, Notification } from 'element-ui';
Vue.config.productionTip = false
Vue.component(Button.name, Button);
Vue.component(Menu.name, Menu);
Vue.component(MenuItem.name, MenuItem);
Vue.component(Submenu.name, Submenu);
Vue.component(Form.name, Form);
Vue.component(FormItem.name, FormItem);
Vue.component(Input.name, Input);
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;
Vue.use(axios);
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
register 部分代码:我这里与之前不同的是在 register.vue 中加入了 email 字段,
下面开始写发送请求的代码:
UserRegister.vue
<template>
<div class="register-form">
<el-form :model="registerForm" :rules="rules" ref="registerForm" @submit.native.prevent="handleRegister">
<el-form-item label="用户名:" prop="username">
<el-input v-model="registerForm.username"></el-input>
</el-form-item>
<el-form-item label="邮箱:" prop="email">
<el-input v-model="registerForm.email"></el-input>
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input type="password" v-model="registerForm.password"></el-input>
</el-form-item>
<el-form-item label="确认密码:" prop="confirmPassword">
<el-input type="password" v-model="registerForm.confirmPassword"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('registerForm')">注册</el-button>
<el-button @click="resetForm('registerForm')">返回登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
data() {
return {
registerForm: {
username: '',
email: '',
password: '',
confirmPassword: '', // 将 confirmPassword 纳入 registerForm
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 5, max: 16, message: '长度在 5 到 16 个字符', trigger: 'blur' },
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] },
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 5, max: 16, message: '长度在 5 到 16 个字符', trigger: 'blur' },
],
confirmPassword: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{ validator: this.validateConfirm, trigger: 'blur' },
],
},
};
},
methods: {
...mapActions('userModule', { userRegister: 'register' }),
validateConfirm(rule, value, callback) {
if (value !== this.registerForm.password) {
callback(new Error('两次输入密码不一致'));
} else {
callback();
}
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
// 发送注册请求
this.userRegister(this.registerForm).then(() => {
this.$message({
showClose: true,
message: '提交成功',
type: 'success',
});
this.$router.replace({ name: 'Home' });
}).catch(() => {
this.$message({
showClose: true,
message: '注册请求失败',
type: 'error',
});
});
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<style scoped>
.register-form {
width: 300px;
margin: 100px auto;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
</style>
UserLogin.vue 代码
<template>
<div class="login-container">
<el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="loginForm.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
data() {
return {
loginForm: {
username: '',
password: '',
},
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' },
],
},
};
},
methods: {
...mapActions('userModule', { userLogin: 'login' }),
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$message({
showClose: true,
message: '提交成功',
type: 'success'
});
// 在这里你可以添加登录逻辑,比如发送请求到服务器
console.log(this.loginForm)
this.userLogin(this.loginForm).then(() => {
// 跳转页面
this.$router.replace({ name: 'Home' });
}).catch(() => {
this.$message({
showClose: true,
message: '登录请求错误',
type: 'error'
});
});
} else {
this.$message({
showClose: true,
message: '提交请求失败',
type: 'error'
});
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
};
</script>
<style scoped>
.login-container {
width: 400px;
margin: 200px auto;
/* border: 1px red ridge; */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 添加的阴影效果 */
}
</style>
运行结果:
我们右击空白的地方点击检查
如果配置的和显示的结果一致那么就成功了,第三天的任务算是完成了。
后面根据本人情况再进行选择性的更。