Vue2项目中发送请求业务流程和后续完善
场景:我通过Vue CIL创建了一个项目,在简单布局和完成基础功能之后,我需要向服务器发送请求。
例如:我在登陆界面获取了用户输入的数据,然后向服务器发送包含用户凭据(用户/手机号和密码)的 POST 请求来获取令牌(Token)。
一、完成基本功能
1.点击按钮发送请求
基本结构
<!-- 基于element -->
<el-button type="primary" @click="submitForm">登录</el-button>
submitForm() {
this.$refs.formRef.validate(async(value) => {
if (value) {
// 校验完成后
console.log('发送请求')
}
})
},
为了方便管理,我们将请求写在vuex的actions里
methods: {
submitForm() {
this.$refs.formRef.validate(async(value) => {
if (value) {
// 发送请求
// 请求写在vuex的actions里
const res = await this.$store.dispatch('user/loginAction', { mobile: this.ruleForm.mobile, password: this.ruleForm.password })
if (res) {
// 如果登录请求成功
this.$router.push('/')
// 完成登录路由跳转
}
}
})
},
resetForm() {}
}
二、创建Vuex
为了以后项目管理我们在这也将Vuex拆分成不同模块
store文件里创建modules文件夹存放不同模块
在modules文件夹存放user.js
1.创建 Vuex Store 实例
在store文件夹里创建index.js
// 引入 Vue.js 和 Vuex 插件
import Vue from 'vue';
import Vuex from 'vuex';
// 引入全局的 getters,用于获取全局状态
import getters from './getters';
// 引入用户登录模块,用于管理用户登录相关的状态和操作
import user from './modules/user';
// 在 Vue 中使用 Vuex 插件
Vue.use(Vuex);
// 创建一个 Vuex Store 实例
const store = new Vuex.Store({
// 注册模块,这里只注册了一个用户模块
modules: {
user,
},
// 注册全局的 getters
getters,
});
// 导出创建好的 Vuex Store 实例,以便在 Vue 应用中使用
export default store;
注意别忘记在main.js里导入
全局导入
在main.js里添加
// 导入 Vue 框架和 App 组件
import Vue from 'vue'
import App from './App.vue'
// 导入 Vue 路由、Vuex 状态管理
import router from './router'
import store from '@/store'
// 在控制台禁用生产提示
Vue.config.productionTip = false
// 创建一个新的 Vue 实例,传入 Vuex store、Vue Router 和 App 组件,并挂载到指定的元素上
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
2.定义全局的getters
在store文件里创建getters.js
// 定义全局的 getters,用于获取全局状态中的特定值
const getters = {
// 获取用户模块中的 token 值
token: state => state.user.token,
// 获取用户模块中的 userInfo 对象中的 userId 值
userId: state => state.user.userInfo.userId,
};
// 导出全局的 getters,以便在 Vuex 中使用
export default getters;
3.创建用户登录相关模块
store文件里创建user.js存放登录验证方法
export default {
namespaced: true, // 命名空间
state: {
},
mutations: {
},
actions: {
loginAction(context, payload) {
// context 上下文对象 是一个包含了与当前模块有关的属性和方法的对象
// payload 载荷 是一个传递给 action 的参数,可以包含任意类型的数据。
console.log('在这里用调用使用axios发送请求的方法')
}
}
}
这个时候就需要利用axios向服务器发送请求了,为了方便维护管理和复用,我们将请求拆分为不同模块。
后续步骤:
- 先封装使用 Axios 库创建的 HTTP 请求服务模块
- 再设置请求拦截器在发送请求的时候添加Token到请求头,设置响应拦截器处理服务器返回的内容
这里的Token一般是登录身份验证获取成功服务器返回的,以后的请求会用到,所以在这里也完善了对Token的处理
三、发送请求
1.封装Axios实例
utils工具库文件夹里创建request.js请求服务模块
// 引入 Axios 库,用于发送 HTTP 请求
import axios from 'axios';
// 引入用于获取 Token 的工具函数
import { getToken } from './auth';
// 引入 Vuex 的 store 实例,用于管理应用状态
import store from '@/store';
// 引入 Vue Router 实例,用于进行页面导航
import router from '@/router';
// 创建 Axios 实例
const service = axios.create({
// 将 API 地址进行拼接,替换 '地址' 为具体的 API 地址
baseURL: '地址', // 设置基础 URL
timeout: 5000 // 设置请求超时时间
});
// 请求拦截器
service.interceptors.request.use(
config => {
// 在请求发送前的处理逻辑
const token = getToken(); // 获取 Token
if (token) {
config.headers.Authorization = `Bearer ${token}`; // 添加认证信息到请求头
}
return config;
},
error => {
// 处理请求错误
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
response => {
// 处理成功响应
if (response.data.success) {
// 返回得到的数据
return response.data;
} else {
// 处理失败响应
return Promise.reject(response);
}
},
error => {
// 处理响应错误
if (error.response.status === 401) {
// 处理未授权错误,例如 token 过期
store.commit('user/delTokenMutation'); // 提交删除 Token 的 mutation
router.push('/login'); // 跳转到登录界面
return Promise.reject(error);
}
// 处理其他响应错误
return Promise.reject(error);
}
);
// 导出 Axios 实例,以便在其他地方使用
export default service;
这里用到了
getToken()
来获取存储在验证成功后的存储在本地的Token,是为了以后在其他地方发送请求需要验证Token,一般只是登录验证请求是不需要Token的
2.封装Token相关方法
utils工具库文件夹里创建auth.js处理Token模块(cookie)
// 引入名为 'js-cookie' 的第三方库,用于方便地处理 cookie 操作
import Cookies from 'js-cookie'
// 定义一个常量 TokenKey,用于标识存储在 cookie 中的 token 的键名
const TokenKey = 'vue_admin_template_token'
// 获取 cookie 中存储的 token 值
export function getToken() {
return Cookies.get(TokenKey)
}
// 设置 cookie 中存储的 token 值
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
// 从 cookie 中移除存储的 token 值
export function removeToken() {
return Cookies.remove(TokenKey)
}
到这里请求服务模块就基本完善了
为了以后的维护管理我们需要将请求路径(API 路径)封装到同一个文件下
3.封装Api
在api文件下创建user.js
import request from '@/utils/request'
// 验证登录
export function loginRequest(data) {
return request({
url: '/sys/login',
method: 'post',
data
})
}
4.完善请求
再回到store文件里的中modules文件夹里的user.js去完善请求
// 引入用户登录相关的 API 请求函数
import { loginRequest } from '@/api/user'
// 引入用于处理 Token 的工具函数
import { getToken, setToken } from '@/utils/auth'
// 定义 Vuex 模块,用于管理用户相关的状态和行为
export default {
namespaced: true, // 启用命名空间,确保模块的状态不会与其他模块冲突
state: {
token: getToken() || '', // 初始状态中的 token 从本地存储中获取,默认为空字符串
userInfo: {} // 初始状态中的用户信息为空对象
},
mutations: {
// 处理用户登录成功的 mutation,更新状态中的 token 和本地存储的 token
loginMutation(state, payload) {
state.token = payload // 更新状态中的 token
setToken(payload) // 将 token 存储到本地
},
// 处理设置用户信息的 mutation,更新状态中的用户信息
setUserInfoMutation(state, payload) {
state.userInfo = payload // 更新状态中的用户信息
},
// 处理用户登出的 mutation,清空状态中的 token 和用户信息,同时清空本地存储的 token
delTokenMutation(state) {
state.token = '' // 清空状态中的 token
state.userInfo = {} // 清空状态中的用户信息
setToken('') // 清空本地存储的 token
}
},
actions: {
// 处理用户登录的 action,调用登录 API 请求,提交登录成功的 mutation
async loginAction(context, payload) {
const { data } = await loginRequest(payload) // 调用登录请求函数
context.commit('loginMutation', data) // 提交登录成功的 mutation
return Promise.resolve(true) // 返回一个 Promise,表示登录成功
}
}
}
到了这里就可以正常发送请求了
四、相关介绍
1.请求写在Vuex里好处
异步操作: Actions 允许您执行异步操作,例如从服务器获取数据。这对于处理异步逻辑(如 API 调用)非常有用,因为您可以在 action 中执行异步操作,而不会阻塞应用的主线程。
统一的状态管理: 将请求逻辑放在 actions 中有助于保持应用的状态管理统一。这样,您可以在一个地方集中处理数据获取、变更状态等逻辑,使代码更易于维护和理解。
可测试性: 将请求逻辑从组件中分离到 actions 中,使得您更容易编写单元测试。您可以通过测试 actions 中的函数,而无需涉及组件渲染和生命周期。
重用性: 将请求逻辑放在 actions 中使得这些逻辑更容易被其他组件或 actions 重用。如果多个组件需要执行相似的异步操作,可以在 actions 中定义一个通用的 action,并在需要的地方调用它。
清晰的代码结构: 将异步逻辑从组件中抽离出来有助于保持组件代码的简洁和清晰。组件可以专注于用户界面的交互,而异步逻辑则由 actions 处理。
2.Vuex模块优点
代码结构清晰: 拆分 Vuex 模块使得项目的代码结构更加清晰和有序。每个模块可以专注于处理特定的业务逻辑,减少了代码文件的复杂性,提高了代码的可读性。
模块化开发: 每个 Vuex 模块都可以看作是一个独立的模块,具有自己的状态、mutations、actions 等。这样的模块化开发使得开发团队可以更容易地分工协作,每个团队成员可以专注于开发和维护特定的功能模块。
复用性提高: 拆分成不同模块后,每个模块可以更容易地被其他部分或其他项目复用。例如,一个处理用户信息的模块可以在多个组件或页面中复用,而不需要重复编写相同的逻辑。
更好的命名空间管理: 每个模块都拥有自己的命名空间,防止命名冲突。这意味着在不同模块中可以使用相同的 mutation 名称,而不会导致冲突。
可维护性增强: 每个模块的逻辑都相对较小且清晰,使得对特定功能的维护和修改更加容易。开发者可以更容易理解和修改与其当前任务相关的部分,而不会影响整体代码的稳定性。
懒加载优化性能: Vuex 模块可以采用懒加载的方式,只在需要时才被加载,从而减小初始加载的体积,提高应用的启动性能。
独立测试: 拆分模块使得单元测试更加容易进行。可以独立测试每个模块的 mutations、actions 等,确保每个模块的功能单元测试通过,提高代码质量。
逻辑分离: 不同模块的职责分明,每个模块负责特定的业务逻辑。这样逻辑分离使得问题定位和修复更为容易,降低了潜在的错误发生的概率。
3.Axios请求模块优点
代码组织和结构清晰: 将 Axios 请求模块化使得项目结构更加清晰有序。每个模块可以专注于处理特定业务或功能的请求,便于代码组织和维护。
可重用性提高: 封装成模块的请求函数可以在整个应用中轻松地被重用。例如,如果有多个组件需要发送相同类型的请求,可以直接引入模块并调用函数,避免了重复编写相同的请求逻辑。
逻辑分离: 将请求逻辑从组件中提取到独立的模块中,有助于逻辑的分离。组件可以专注于用户界面的交互,而请求的处理则由模块负责。
可维护性提高: 每个模块都可以看作是一个独立单元,容易进行测试和维护。如果需要修改或添加某个请求的逻辑,只需在相应的模块中进行修改,不会影响到其他部分。
错误处理一致性: 在模块中可以统一处理请求的错误,例如处理网络错误、服务器错误等。这样可以确保在整个应用中错误处理的一致性。
懒加载优化性能: 可以按需加载只需要的请求模块,而不是一次性加载整个 Axios 请求逻辑。这有助于减小初始加载体积,提高应用的启动性能。
可扩展性增强: 如果项目需求增加或变更,可以更方便地扩展或修改特定模块的请求逻辑,而不会牵扯到整个项目的代码。
便于维护请求配置: 如果需要在所有请求中共享相同的配置,例如基础 URL、超时时间等,可以在模块中集中配置,便于维护。