axios is a lightweight HTTP client that performs HTTP requests based on the XMLHttpRequest
service, supports rich configuration, supports Promise, and supports browsing Server side and Node.js side. Since Vue2.0, Youda announced that it will cancel the official recommendation of vue-resource
and recommend axios instead. Now axios has become the first choice for most Vue developers. (If you are not familiar with axios, you can view its API here.) [Related recommendations: vue.js video tutorial]
Before encapsulating, let’s take a look at it first, without encapsulation In this case, what an axios request looks like in an actual project.
It probably looks like this:
axios('http://localhost:3000/data', { method: 'GET', timeout: 1000, withCredentials: true, headers: { 'Content-Type': 'application/json', Authorization: 'xxx', }, transformRequest: [function (data, headers) { return data; }], // 其他请求配置... }) .then((data) => { // todo: 真正业务逻辑代码 console.log(data); }, (err) => { if (err.response.status === 401) { // handle authorization error } if (err.response.status === 403) { // handle server forbidden error } // 其他错误处理..... console.log(err); });
You can see that in this code, the page code logic is only on line 15, and a large block of request configuration above The code and a large chunk of response error handling code below have almost nothing to do with the page function, and these contents are similar in every request, and some parts are even exactly the same.
1. Encapsulation steps
The essence of encapsulation is to add various things outside the content to be encapsulated, and then put them It is presented to users as a new whole to achieve expansion and ease of use.
Encapsulationaxios
What needs to be done is to configure the configuration common to all HTTP requests on axios in advance, reserve the necessary parameters and interfaces, and then use it as a new The axios returns.
The directory structure is as follows (generated by Vue-cli 3.0):
##|--public/|--mock/
| |--db.json # My new interface simulation data
|--src/
| |--assets/
| |--components/
| |--router/
| |--store/
| |--views/
| |--Home.Vue
| |--App.vue
| |--main.js
| |--theme.styl
|--package.json
|...
2. Package target
on the Home page , making an axios request is as simple as calling a method with only a few parameters, so I can focus on the business code.1. Encapsulate axios into a separate file
cd src mkdir utils touch http.js
// src/utils/http.js import axios from 'axios';
//src/utils/http.js //... class NewAxios { }
baseURL according to
process.env.NODE_ENV , so that the project can automatically switch the request host address in different environments by simply executing the corresponding packaging command.
// src/utils/http.js //... const getBaseUrl = (env) => { let base = { production: '/', development: 'http://localhost:3000', test: 'http://localhost:3001', }[env]; if (!base) { base = '/'; } return base; }; class NewAxios { constructor() { this.baseURL = getBaseUrl(process.env.NODE_ENV); } }
timeout attribute, I usually set it to 10 seconds.
// src/utils/http.js //... class NewAxios { constructor() { //... this.timeout = 10000; } }
widthCredentials property is set to
true
// src/utils/http.js //... class NewAxios { constructor() { //... this.withCredentials = true; } }
request method, create a new axios instance, receive the request configuration parameters, process the parameters, add configuration, and return the axios instance The request result (a promise object).
create method of
axios so that each request is a new axios instance.
// src/utils/http.js //... class NewAxios { //... request(options) { // 每次请求都会创建新的axios实例。 const instance = axios.create(); const config = { // 将用户传过来的参数与公共配置合并。 ...options, baseURL: this.baseURL, timeout: this.timeout, withCredentials: this.withCredentials, }; // 配置拦截器,支持根据不同url配置不同的拦截器。 this.setInterceptors(instance, options.url); return instance(config); // 返回axios实例的执行结果 } }
token here.
// src/utils/http.js //... class NewAxios { //... // 这里的url可供你针对需要特殊处理的接口路径设置不同拦截器。 setInterceptors = (instance, url) => { instance.interceptors.request.use((config) => { // 请求拦截器 // 配置token config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || ''; return config; }, err => Promise.reject(err)); } //... }
then or
catch processing deal with. For example, filtering response data, and more importantly, unified error processing for various response error codes, network disconnection processing, etc.
// src/utils/http.js //... class NewAxios { //... setInterceptors = (instance, url) => { //... instance.interceptors.response.use((response) => { // 响应拦截器 // todo: 想根据业务需要,对响应结果预先处理的,都放在这里 console.log(); return response; }, (err) => { if (err.response) { // 响应错误码处理 switch (err.response.status) { case '403': // todo: handler server forbidden error break; // todo: handler other status code default: break; } return Promise.reject(err.response); } if (!window.navigator.online) { // 断网处理 // todo: jump to offline page return -1; } return Promise.reject(err); }); } //... }
In addition, in the interceptor, it is also suitable to place buffering effects such as loading: Display loading in the request interceptor and remove loading in the response interceptor. In this way, all requests will have a unified loading effect.
// src/utils/http.js //... export default new NewAxios();
The final complete code is as follows:
// src/utils/http.js import axios from 'axios'; const getBaseUrl = (env) => { let base = { production: '/', development: 'http://localhost:3000', test: 'http://localhost:3001', }[env]; if (!base) { base = '/'; } return base; }; class NewAxios { constructor() { this.baseURL = getBaseUrl(process.env.NODE_ENV); this.timeout = 10000; this.withCredentials = true; } // 这里的url可供你针对需要特殊处理的接口路径设置不同拦截器。 setInterceptors = (instance, url) => { instance.interceptors.request.use((config) => { // 在这里添加loading // 配置token config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || ''; return config; }, err => Promise.reject(err)); instance.interceptors.response.use((response) => { // 在这里移除loading // todo: 想根据业务需要,对响应结果预先处理的,都放在这里 return response; }, (err) => { if (err.response) { // 响应错误码处理 switch (err.response.status) { case '403': // todo: handler server forbidden error break; // todo: handler other status code default: break; } return Promise.reject(err.response); } if (!window.navigator.online) { // 断网处理 // todo: jump to offline page return -1; } return Promise.reject(err); }); } request(options) { // 每次请求都会创建新的axios实例。 const instance = axios.create(); const config = { // 将用户传过来的参数与公共配置合并。 ...options, baseURL: this.baseURL, timeout: this.timeout, withCredentials: this.withCredentials, }; // 配置拦截器,支持根据不同url配置不同的拦截器。 this.setInterceptors(instance, options.url); return instance(config); // 返回axios实例的执行结果 } } export default new NewAxios();
axios Encapsulation is 80% complete. We still need to further combine axios with the interface and encapsulate it one layer further to achieve the encapsulation goal I set at the beginning.
3. Use the new axios packaging API
home.js
。我们需要把接口根据一定规则分好类,一类接口对应一个js文件。这个分类可以是按页面来划分,或者按模块等等。为了演示更直观,我这里就按页面来划分了。实际根据自己的需求来定。// src/api/home.js import axios from '@/utils/http'; export const fetchData = options => axios.request({ ...options, url: '/data', }); export default {};
在 api 目录下新建 index.js,把其他文件的接口都在这个文件里汇总导出。
// src/api/index.js export * from './home';
这层封装将我们的新的axios封装到了更简洁更语义化的接口方法中。
现在我们的目录结构长这样:
|--public/
|--mock/
| |--db.json # 接口模拟数据
|--src/
| |--api/ # 所有的接口都集中在这个目录下
| |--home.js # Home页面里涉及到的接口封装在这里
| |--index.js # 项目中所有接口调用的入口
| |--assets/
| |--components/
| |--router/
| |--store/
| |--utils/
| |--http.js # axios封装在这里
| |--views/
| |--Home.Vue
| |--App.vue
| |--main.js
| |--theme.styl
|--package.json
|...
4.使用封装后的axios
现在我们要发HTTP请求时,只需引入 api 下的 index.js 文件就可以调用任何接口了,并且用的是封装后的 axios。
// src/views/Home.vue <template> <div class="home"> <h1>This is home page</h1> </div> </template> <script> // @ is an alias to /src import { fetchData } from '@/api/index'; export default { name: 'home', mounted() { fetchData() // axios请求在这里 .then((data) => { console.log(data); }) .catch((err) => { console.log(err); }); }, }; </script>
axios请求被封装在fetchData函数里,页面请求压根不需要出现任何axios API,悄无声息地发起请求获取响应,就像在调用一个简单的 Promise 函数一样轻松。并且在页面中只需专注处理业务功能,不用被其他事物干扰。
The above is the detailed content of Parse the encapsulation request of axios in vue (with step code). For more information, please follow other related articles on the PHP Chinese website!