在之前我们讲过axios的基本使用方法【axios】axios的基本使用,在实际的Vue项目中,我们并不使用这种方法。当时还未实现项目的规范化,没有严格划分组件和模块,只是把所有东西都写在一个html文件中,现在我们要从前端工程化的角度来看如何使用axios。
假设我们有一个Vue项目,App根组件中包含一个Left组件和一个Right组件,Left组件中有一个按钮,点击后发送GET请求。Right组件中有一个按钮,点击后发送POST请求。基本页面构成如下:
首先需要安装axios包,后续才可以在项目中使用axios。在终端执行npm i axios -S
,即可把axios安装到项目中。
Left组件的script标签内容:
<script>
// 导入axios模块
import axios from 'axios'
export default {
data() {
return {
bookList: {}
}
},
methods: {
// 点击事件
//
async getInfo() {
const { data: res } = await axios.get('http://www.liulongbin.top:3006/api/getbooks')
console.log(res)
// 一般把请求回来的数据转存到data中
this.bookList = res
}
}
}
script>
Right组件的script标签内容:
<script>
// 导入axios模块
import axios from 'axios'
export default {
methods: {
// 点击事件
//
async postInfo() {
const { data: res } = await axios.post('http://www.liulongbin.top:3006/api/post', { name: 'zs', age: 20 })
console.log(res)
// 不再演示数据转存到data的过程
}
}
}
script>
均可以成功请求,但是这种方法的缺点是:每使用一次axios,就要导入一次,只要这个.vue组件使用了axios,就需要导入axios模块,各组件之间不能互相使用(不通用),比较麻烦。因此我们希望axios全局可用。
(1) 因为我们希望axios 全局可用,所以需要在 main.js文件中进行相应配置,步骤如下:
import Vue from 'vue'
import App from './App.vue'
// 1.导入axios模块
import axios from 'axios'
Vue.config.productionTip = false
// 2.将axios挂载到Vue原型上
Vue.prototype.$http = axios
new Vue({
render: h => h(App)
}).$mount('#app')
【注意】将axios挂载到Vue原型上时,其中
$http
的名字是任意的,表示我们在Vue原型上挂载了一个名为$http
的属性(方法),它的值为axios
。习惯上,我们都把这个属性命名为$http
。
(2) 为了简化.vue组件实例的调用,可以配置一个请求根路径,之后使用时只需要传入根路径之后的部分即可。
import Vue from 'vue'
import App from './App.vue'
// 1.导入axios模块
import axios from 'axios'
Vue.config.productionTip = false
// 3.配置请求根路径
axios.defaults.baseURL = 'http://www.liulongbin.top:3006'
// 2.将axios挂载到Vue原型上
Vue.prototype.$http = axios
new Vue({
render: h => h(App)
}).$mount('#app')
(3)在组件中的使用方法:
$http
的属性,而.vue组件又是一个Vue实例,所以可以通过this.$http
拿到axios,然后就可以正常使用了。Left组件的script标签内容:
<script>
// 不再需要导入axios模块,直接删除导入代码
export default {
data() {
return {
bookList: {}
}
},
methods: {
async getInfo() {
const { data: res } = await this.$http.get('/api/getbooks')
console.log(res)
// 一般把请求回来的数据转存到data中
this.bookList = res
}
}
}
script>
Right组件的script标签内容:
<script>
export default {
methods: {
async postInfo() {
const { data: res } = await this.$http.post('/api/post', { name: 'zs', age: 20 })
console.log(res)
// 不再演示数据转存到data的过程
}
}
}
script>
【缺点】:请求数据的代码复用性差,如果不同的组件需要请求同一份数据,每请求一次,就要写一次请求函数。
在和src目录同级的地方,新建一个utils文件夹,表示用到的工具,在里面新建一个request.js文件,这个就是封装axios的模块。谁需要用到这个根路径去请求数据,谁就导入这个模块。
request.js文件的内容:
// 导入axios
import axios from 'axios'
// 通过axios.create方法创建一个axios实例,用request接收
const request = axios.create({
// 指定请求的根路径
baseURL: 'http://www.liulongbin.top:3006'
})
export default request
使用方法(以Left组件为例):
<script>
// 导入request模块
import request from '@/utils/request.js'
export default {
data() {
return {
bookList: {}
}
},
methods: {
async getInfo() {
// 假设需要传一个参数,这里的参数是假的,演示用
const { data: res } = await request.get('/api/getbooks', {
params: { id: 1 }
})
console.log(res)
// 一般把请求回来的数据转存到data中
this.bookList = res
}
}
}
script>
【拓展】一个项目中可以封装多个axios模块,如果需要用到多个不同的请求根路径,那么每一个根路径封装一个对应的axios模块,然后各模块之间互不相同,互不影响。
但是这个时候还是没有解决代码复用性低的问题,请求函数会重复写。此时我们再把请求数据的代码封装成一个API模块。
在和src目录同级的地方,新建一个api文件夹,表示自己写的api,在里面新建一个bookAPI.js文件,这个就是封装的books的模块,关于book的所有API接口,都可以封装到这个模块。谁需要用到这个API接口,谁就导入这个模块。
bookAPI.js文件的内容:
// 导入request模块
import request from '@/utils/request.js'
// 向外按需导出一个接口函数
export const getBookListAPI = function() {
// 记得一定要把请求到的promise对象return出去
return request.get('/api/getbooks', {
// 假设需要传一个参数,这里的参数是假的,演示用
params: { id: 1 }
})
}
<script>
// 按需导入bookAPI
import { getBookListAPI } from '@/api/bookAPI.js'
export default {
data() {
return {
bookList: {}
}
},
methods: {
async getInfo() {
// 调用getBookListAPI请求数据
const { data: res } = await getBookListAPI()
console.log(res)
// 一般把请求回来的数据转存到data中
this.bookList = res
}
}
}
script>
这就实现了请求数据接口的封装,提高了代码的复用性。