axios ist ein leichter HTTP-Client, der HTTP-Anfragen basierend auf dem Dienst XMLHttpRequest
ausführt. Er unterstützt umfangreiche Konfigurationen, Promise, Browser und Node.js. Seit Vue2.0 hat Youda angekündigt, die offizielle Empfehlung von vue-resource
aufzuheben und stattdessen axios zu empfehlen. Mittlerweile ist Axios für die meisten Vue-Entwickler zur ersten Wahl geworden. (Wenn Sie mit Axios nicht vertraut sind, können Sie sich die API hier ansehen.) [Verwandte Empfehlungen: vue.js-Video-Tutorial】XMLHttpRequest
服务来执行 HTTP 请求,支持丰富的配置,支持 Promise,支持浏览器端和 Node.js 端。自Vue2.0起,尤大大宣布取消对vue-resource
的官方推荐,转而推荐 axios。现在 axios 已经成为大部分 Vue 开发者的首选。( 如果你还不熟悉 axios,可以在这里查看它的API。)【相关推荐:vue.js视频教程】
封装前,先来看下,不封装的情况下,一个实际项目中axios请求的样子。
大概是长这样:
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); });
可以看到在这段代码中,页面代码逻辑只在第15行处,上方的一大块请求配置代码和下方一大块响应错误处理代码,几乎跟页面功能没有关系,而且每个请求中这些内容都差不多,甚至有的部分完全一样。
1.封装步骤
封装的本质就是在待封装的内容外面添加各种东西,然后把它们作为一个新的整体呈现给使用者,以达到扩展和易用的目的。
封装 axios
要做的事情,就是把所有HTTP请求共用的配置,事先都在axios上配置好,预留好必要的参数和接口,然后把它作为新的axios返回。
目录结构如下(由Vue-cli 3.0 生成):
|--public/
|--mock/
| |--db.json # 我新建的接口模拟数据
|--src/
| |--assets/
| |--components/
| |--router/
| |--store/
| |--views/
| |--Home.Vue
| |--App.vue
| |--main.js
| |--theme.styl
|--package.json
|...
2.封装目标
在 Home 页,发起 axios 请求时就像调用一个只有少量参数的方法一样简单,这样我就可以专注业务代码了。
1. 将 axios 封装到一个独立的文件
cd src mkdir utils touch http.js
// src/utils/http.js import axios from 'axios';
//src/utils/http.js //... class NewAxios { }
根据process.env.NODE_ENV
配置不同的 baseURL
,使项目只需执行相应打包命令,就可以在不同环境中自动切换请求主机地址。
// 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
属性,我一般设置10秒。
// src/utils/http.js //... class NewAxios { constructor() { //... this.timeout = 10000; } }
widthCredentials
属性设为true
// src/utils/http.js //... class NewAxios { constructor() { //... this.withCredentials = true; } }
在 request
方法里,创建新的axios实例,接收请求配置参数,处理参数,添加配置,返回axios实例的请求结果(一个promise对象)。
你也可以不创建,直接使用默认导出的axios实例,然后把所有配置都放到它上面,不过这样一来整个项目就会共用一个axios实例。虽然大部分项目下这样够用没问题,但是有的项目中不同服务地址的请求和响应结构可能完全不同,这个时候共用一个实例就没办法支持了。所以为了封装可以更通用,更具灵活性,我会使用axios
的create
方法,使每次发请求都是新的axios实例。
// 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凭证、统一设置语言、统一设置内容类型、指定数据格式等等。做完后记得返回这个配置,否则整个请求不会进行。
我这里就配置一个token
。
// 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
或catch
处理前对响应数据进行一轮预先处理。比如过滤响应数据,更多的,是在这里对各种响应错误码进行统一错误处理,还有断网处理等等。
我这里就判断一下403和断网。
// 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); }); } //... }
另外,在拦截器里,还适合放置loading等缓冲效果:在请求拦截器里显示loading,在响应拦截器里移除loading。这样所有请求就都有了一个统一的loading
效果。
// src/utils/http.js //... export default new NewAxios();
最后完整的代码如下:
// 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
Es sieht wahrscheinlich so aus:
🎜// src/api/home.js import axios from '@/utils/http'; export const fetchData = options => axios.request({ ...options, url: '/data', }); export default {};
axios
tun muss, besteht darin, die Konfiguration, die allen HTTP-Anforderungen auf axios gemeinsam ist, im Voraus zu konfigurieren, die erforderlichen Parameter und Schnittstellen zu reservieren und sie dann als neues axios zurückzugeben. 🎜🎜🎜Die Verzeichnisstruktur ist wie folgt (generiert von Vue-cli 3.0): 🎜🎜🎜|--public/🎜|--mock/🎜|. |--db.json # Meine neuen Schnittstellensimulationsdaten 🎜 |--src/🎜|. |--components/🎜| |--views/🎜| |- -App.vue🎜|. |--main.js🎜|--package.json🎜|...🎜🎜🎜2 Startseite: Das Erstellen einer Axios-Anfrage ist so einfach wie das Aufrufen einer Methode mit nur wenigen Parametern, sodass ich mich auf meinen Geschäftscode konzentrieren kann. 🎜🎜🎜1. Axios in eine separate Datei kapseln🎜🎜
// src/api/index.js export * from './home';
// 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>
baseURL
, damit das Projekt die Anforderungshostadresse in verschiedenen Umgebungen automatisch wechseln kann, indem Sie einfach den entsprechenden Paketierungsbefehl ausführen. 🎜rrreeetimeout
. Normalerweise stelle ich es auf 10 Sekunden ein. 🎜rrreeewidthCredentials
-Eigenschaft ist auf true
🎜rrreeerequest
eine neue Axios-Instanz, empfangen Sie die Anforderungskonfigurationsparameter, verarbeiten Sie die Parameter, fügen Sie Konfiguration hinzu, und die Anforderung für das Axios-Instanzergebnis (ein Versprechensobjekt) zurückgeben. 🎜🎜Sie können die standardmäßig exportierte Axios-Instanz auch direkt verwenden, ohne sie zu erstellen, und dann alle Konfigurationen darauf ablegen, aber auf diese Weise teilt sich das gesamte Projekt eine Axios-Instanz. Obwohl dies für die meisten Projekte ausreichend ist, können die Anforderungs- und Antwortstrukturen verschiedener Dienstadressen in einigen Projekten völlig unterschiedlich sein. In diesem Fall kann die gemeinsame Nutzung einer Instanz dies nicht unterstützen. Um die Kapselung vielseitiger und flexibler zu gestalten, verwende ich die Methode create
von axios
, sodass jede Anfrage eine neue Axios-Instanz ist. 🎜rrreee🎜Da der Inhalt der Interceptor-Konfiguration relativ groß ist, ist er in eine interne Funktion gekapselt. 🎜Token
konfigurieren. 🎜rrreeethen
oder catch</ der Anfrage aus. Code> Verarbeitung behandeln. Zum Beispiel das Filtern von Antwortdaten und, was noch wichtiger ist, eine einheitliche Fehlerverarbeitung für verschiedene Antwortfehlercodes, die Verarbeitung von Netzwerkunterbrechungen usw. 🎜🎜Ich werde hier 403 und Verbindungsabbruch beurteilen. 🎜rrreee🎜🎜Darüber hinaus ist es im Interceptor auch geeignet, Puffereffekte wie das Laden zu platzieren: 🎜Laden im Anforderungs-Interceptor anzeigen und Laden im Antwort-Interceptor entfernen. Auf diese Weise haben alle Anfragen einen einheitlichen <code>Ladeeffekt
. 🎜axios
-Kapselung zu 80 % abgeschlossen . Wir müssen Axios noch weiter mit der Schnittstelle kombinieren und eine Schicht weiter kapseln, um das Kapselungsziel zu erreichen, das ich mir zu Beginn gesetzt habe. 🎜🎜🎜3. Verwenden Sie die neue Axios-Paket-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 函数一样轻松。并且在页面中只需专注处理业务功能,不用被其他事物干扰。
Das obige ist der detaillierte Inhalt vonAnalysieren Sie die Kapselungsanforderung von Axios in Vue (mit Schrittcode).. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!