我爱编程

【Vue18】axios

2018-05-27  本文已影响0人  八宝君

实现ajax的工具

ajax有很多工具,比如浏览器自带的fetch,或者vue以前推荐的vue-resource。现在vue官方推荐用的是axios,它可以实现跨平台的数据请求,比如说浏览器端可以发xhr的请求,服务器上可以发送http的请求。
这里用的是axios

引入axios

首先得安装axios,npm install axios --save,安装完之后要记得去引入。去哪里引入呢?
首先分析一波,比如说首页,一般来说首页是由很多组件构成的,比如说这样:

我是首页
每个组件都有自己的数据,难道每个组件在自己的组件内发送ajax请求吗?
这样做是有问题的,首页一般由n个组件组成,每个组件发送一个ajax请求,那么首页至少有5个ajax请求。那么网站的性能就非常低了。
一般来说整个首页发一个ajax请求就行了。So去首页的那个组件去发送是最好的选择,这个大组件在获取ajax数据后,可以把数据传给每个组件。

还记得组件的生命周期函数中有个mounted吗?
一般ajax数据的获取是放在mounted里面的,页面挂载成功就去请求数据。

举个栗子
如上图:
getHomeInfo: 这个函数是axios请求,具体的函数是要写在methods里的;
/api/index.json: 请求地址,这里是随意写的,根据实际地址来写;
axios返回的是一个promise对象,所以可以用then(this.getHomeInfoSucc)来接收返回结果。
getHomeInfoSucc:是成功时的执行函数。

此时浏览器是这样的:


浏览器报错

返回一个404,因为我们的请求地址是随便写的。

在没有后端的支持下,怎么实现数据的模拟呢?

mock数据

整个项目有一个static目录,这个目录存放的是静态文件。

我就是static目录
static目录下新建一个mock目录,然后新建一个json文件,这里叫做index.json,里面随便写点内容。
为什么要放在static目录下呢?
因为在整个工程里,只有static目录下的内容可以被外部访问到。
比如在浏览器地址下输入这个:
json文件的内容显示了出来
可以看到json文件的内容。
但是如果我们想访问src下的文件,输入这样的地址,会被重定向到首页。
我又回到首页了

So我们可以把本地开发用到的模拟数据,都放在static目录下。(!!!不是随便创个static目录,就可以访问里面的内容,必须要配置,因为我这个项目是直接用的vue-cli,已经自动配置好了)

【PS:这个mock文件夹里放的都是本地的模拟数据,不想提交到线上的话,打开.gitignore文件,添加一下文件夹名就可以了】

.gitignore

还没完,记得修改一下之前的axios请求的地址,。

修改请求地址
成功得到返回结果

等等,还没完。
现在出现了一个新的问题,因为目前用的都是本地模拟的数据,要是代码上线,请求地址肯定不能这样写了,上线前改动代码是有风险的,怎么解决这个问题呢?
可不可以开发环境中依旧用本地请求地址,如果有个转发机制,可以帮助我们把对api下的所有json文件的请求转发到本地的mock文件夹下,这样不就可以了吗?
Vue的脚手架里提供了一个proxy的代理功能,通过这个功能,可以实现上面的构想。
config/index.js里有一个proxyTable,对它进行相应的配置就行。

这样配置
解释一波。
当请求api这个目录的时候,把请求转发到当前服务器的8080端口上,将路径做一个替换,一旦请求的地址是以api开头,就替换成请求本地的mock这个文件夹下。

这个功能实际上是webpack-dev-server提供的,并不真正是Vue提供的。

改完配置项文件的时候,记得要重新运行一下服务器~

传递数据

上面已经用axios获取了数据,现在要将数据传给各个组件了。
先去home组件,也就是首页这个父组件。
给各个组件传值,其实也就是我们之前说的父组件给子组件传值。
举个栗子:
1.父组件内,创建一个data,给子组件通过绑定属性的形式传值(默认值为空)

先创建data里的变量 绑定city属性
2.子组件通过props接收
props接收,然后更改绑定的模板
3.回到父组件,创建数据的存放变量。
拿到数据内容
分解一下步骤:
1)让res = res.data,是为了让json文件内容 = res,如下图,要取得city的值,实际上是res.data.data.city,经过这个赋值步骤后,再拿到city的内容的表达式就是res.data.city
2)做个判断,如果后端正确的返回了结果,并且res有内容项,再执行赋值操作。
3)获取内容赋值。 后面的操作就是拿到内容,然后赋值对应的值,this.city = data.city (这里的data = res.data,做了处理)
将res=res.data

这样就拿到了内容了。

整个流程是,获取到city的内容后,传给了父组件data里的city,然后再传给了子组件(通过属性绑定),子组件接收了这个city,然后就能拿到这个值了。

父组件内,通过list属性传递swiperList数组
子组件内接收list属性,类型为数组,循环的也是list的内容

【子组件之前的data里的数据记得删除】


一个小小的tips:
swiper组件这里可能会有一个小bug,获取到ajax数据之后,展示的第一页是最后一个,而不是索引最靠前的那个,为什么会这样呢?
swiper最初创建的时候是通过空数组创建的(默认值),当ajax获取完之后,swiperList变成真正的数据项,再传给homeSwiper这个组件的时候,list才获取到新数据,重新渲染了新数据对应的很多幻灯片,就是因为初始化创建是根据空数组创建的,才会导致默认显示的是最后一张幻灯片。
怎么解决呢?
swiperList最初的创建不由空数组,而由完整的数据来创建。写一个v-if="list.length",当这个时候传递过来的list是个空数组的时候,swiper不会被创建,只有当真正数据过来之后,swiper才会创。

我是解决方法

但是这样的代码不是很优雅,模板中应该尽量减少逻辑性的代码。
所以在data下增加一个computed计算属性。做一下逻辑处理

这样处理
模板中再更改一下:
更改一下

关于axios拦截器

这部分内容是2018年7月25日的更新,之前自己只会引用axios,进行get或者post之类的请求。后来因为业务需求,有的时候需要对请求和响应进行拦截。
比如说,在每次请求都需要加一个source号,来告诉是xxx渠道的请求,因为可能由于业务原因,对不同渠道的数据进行了划分。难道我们每一次请求接口,都要首先从缓存中拿到source的值,然后再和参数拼接起来一起传过去?
这里就可以用到我们所说的请求拦截了。
也就是封装一个axios,然后在请求之前做一个拦截,将参数多加一个source上去,这样就在封装的时候做一次操作就行了,不用每次请求接口都去拿source
同样的,响应也能做拦截,众所周知,返回的resultCode为一个约定的正确值时,表示data是正确返回,但是有的时候不一定有正确的返回,比如说sourcecode失效了,之类的,这个时候接口会返回一个特定的值,例如我和后台约定的是errorCode返回的如果是LASEB111,就跳转到特定的错误提示页。
我们同样可以统一做拦截,然后一次代码就能让所有的请求只要出现这种错误码。就直接跳转到错误提示页。而不是每一次请求接口,再用多个if...else来对错误码做一次次的判断。
贴一下代码:

请求拦截封装 响应拦截封装
全局配置
到这里还没完,我们仅仅是封装了自己的axios,但是还没有引入。因为这是我们自己封装的axios,引入的时候就像引入插件一样。
首先引入需要的,在这里我们还配置了一些东西,比如请求的时候的loading的效果,还有伴随一些弹窗提示。我用的是mint-ui的弹窗和loading效果。小伙伴可以配置自己相应ui的效果。 引入需要的
请求成功时
请求失败时
记得将方法添加到vue的原型链上。
最后最后,还有一个地方。
main.js里要记得引入然后use

ヾ(◍°∇°◍)ノ゙

上一篇 下一篇

猜你喜欢

热点阅读