发送http我使用的是非常流行的 axios ,我在其基础上,稍微进行简单的封装,然后暴露 request 对象供调用。二次封装主要是为了解决以下几个问题
简化参数,把一些常用参数都赋默认值,简化外部的使用,使得更加通用和利于排查问题。
返回报文统一处理,我们通常需要对些高频的场景做相同的处理,如错误码、未登录等场景,可以在它提供的返回响应拦截器中,统一处理。
防止重复提交,因为网络、后端处理的因素,有时接口响应会较慢,那么用户可能会在非常短的时间内,反复点击按钮,在第一次请求未返回的情况下,会再次发起新的请求,那么我们可以在axios提供的前置拦截器中搞点事情。关于防止重复请求这东东,我在以前的一篇文章有写过, 前端防止用户重复提交-js 感兴趣的小伙伴可以看看。
根据以上几点,下面是我封装的request文件,思路都比较简单,就不多说啦
import axios from 'axios'; import qs from 'qs'; const Axios = axios.create({ baseURL: 'https://www.jb51.net/', timeout: 10000, responseType: 'json', withCredentials: true, headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' } }); const CancelToken = axios.CancelToken; const requestMap = new Map(); // 请求前置拦截器 Axios.interceptors.request.use( config => { // 防重复提交 const keyString = qs.stringify(Object.assign({}, { url: config.url, method: config.method }, config.data)); if (requestMap.get(keyString)) { // 取消当前请求 config.cancelToken = new CancelToken((cancel) => { cancel('Please slow down a little'); }); } requestMap.set(keyString, true); Object.assign(config, { _keyString: keyString }); if (config.method === 'post' || config.method === 'put' || config.method === 'delete') { // 序列化 config.data = qs.stringify(config.data); } return config; }, error => { return Promise.reject(error); } ); // 返回响应拦截器 Axios.interceptors.response.use( res => { // 重置requestMap const config: any = res.config; requestMap.set(config._keyString, false); if (res.status === 200) { return res.data; } // todo 弹窗提示等 console.log(`request error:${res}`); }, error => { return { code: -1 }; } ); /** * @description * 请求 * @param url * @param data * @param method */ const request = (url: string, data = {}, method = 'post') => { return Axios({ method, url, data, params: method.toUpperCase() === 'GET' && data }); }; export { request };
vuex状态管理
这里我根据业务模块来划分文件结构,如下图
分为首页模块和用户模块,每个模块都有自己独立的 state mutations 等,在 store.ts 中,引入各模块的文件,如下
import Vue from 'vue'; import Vuex from 'vuex'; import index from './indexModule/index'; import user from './userModule/user'; Vue.use(Vuex); export default new Vuex.Store({ modules: { user, index } });
大家注意到这里有个 store_types.ts 文件,这个文件主要是为了搭配ts使用的,文件内容如下
export enum UserType { /** * 模块名称 */ 'MODULE_NAME' = 'user', /** * 增加次数 */ 'ADD_COUNT' = 'addCount', /** * 计算属性-获取十倍的值 */ 'GET_TEM_COUNT' = 'getTenCount' }
在看下组件中的使用方式:
<script lang="ts"> import { UserType } from '@/store/store_types'; import { Component, Prop, Vue, Watch,Emit } from 'vue-property-decorator'; import { Action, Getter, Mutation, namespace, State } from 'vuex-class'; @Component export default class Test extends Vue { @State(state => state[UserType.MODULE_NAME].count) public fff!: number; @Getter(`${UserType.MODULE_NAME}/${UserType.GET_TEM_COUNT}`) public tenCount!: number; @Mutation(`${UserType.MODULE_NAME}/${UserType.ADD_COUNT}`) public addCount!: any; } </script>
虽然这么写的确有点绕,但有个好处,我们可以通过注释清晰知道方法和属性的说明
小结
以上是我根据自己工作中常见的场景来设计的,希望能对小伙伴能有帮助,其中设计不当的地方,欢迎小伙伴们在留言区一起探讨哈~也希望大家多多支持脚本之家。
您可能感兴趣的文章: