首发日期:2019-01-29

作者:http://www.cnblogs.com/progor/

修改:

2019-02-11:发现发起请求的封装中的export default 写错了,是export,在后面的代码是使用了export ,但有一个地方使用了export default,export导入的在import的时候需要使用固定的名字,export default在import导入的时候可以使用随意的名字


上节内容回顾

  • npm(介绍,安装,命令)
  • 基于npm的Hello World(学会如何初始化一个vue项目,并启动项目)
  • 项目结构分析(重点是src目录)
  • 用法迁移(根实例怎么创建,页面是怎么渲染的,组件怎么注册,)
  • 小提醒(语法注意,和‘@’)
  • 单文件组件
  • 路由(开启路由,定义路由,带参路由,使用路由(router-link,router-view),嵌套路由,嵌套路由,命名路由,编程式路由,)
  • vuex(actioins,mutaions,state,怎么创建store,怎么读取数据,怎么修改数据)

使用第三方组件库

网上有很多vue的第三方组件库,为了简化开发,我们通常都会使用第三方的组件库。

下面以导入element UI 组件库为例:

首先,安装element UI模块,并把依赖添加到package.json中:

npm install element-ui --save

然后,如果你是要在整个项目中都用到element UI的话,那就在main.js中添加下列代码,这样就可以在所有的组件中使用elmenent UI中的所有组件了:

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

如果你仅仅想使用某个组件的话,可以仅仅在某个组件中使用import来导入element UI的组件。


如何发起请求

我们搭建了一个页面后,通常都希望从后端接口获取数据来渲染页面。现在推荐的发起请求的方式是使用axios来发起请求。

首先,我们要安装axios

npm install axios

然后在组件中使用axios来发请求:

<template>
<div class='hello'>
接受到的数据:{{msg}}
<button @click="getList">获取数据</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Hello',
data () {
return {
msg: ''
}
},
methods: {
getList () {
axios.get('https://api.coindesk.com/v1/bpi/currentprice.json').then(response => {
this.msg = response
})
}
}
}
</script>

上面只演示了axios.get,类似的,还有axios.post,axios.put等等请求方法。

请求错误处理

如果请求失败了,那么不会跳到then,而是交给catch来处理,catch里面的第一个参数就是错误信息:

axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = response.data.bpi))
.catch(error => console.log(error))

请求带参

以get的方式带参:

      axios.get('https://api.coindesk.com/v1/bpi/currentprice.json',{params: {ID: 12345}})
.then(response => {
this.msg = response
})

以post的方式带参:

      axios.post('/user', {firstName: 'Fred', lastName: 'Flintstone'})
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
})

封装处理

在上面的例子中,我们可以看到如果我们想要发送请求,将要在axios.xxx()的参数中写很长的代码。该怎么优化呢?

请求的配置

其实也可以使用axios()来发起请求,axios里面的参数是关于请求的配置,例如:

      var request = {
method: 'post',
url: '/user',
data: {firstName: 'Fred', lastName: 'Flintstone'}
}
axios(request).then(response => (this.msg = response))
.catch(error => {
console.log(error)
})

贴一下可以设置的配置:

{
// `url` 是用于请求的服务器 URL
url: '/user', // `method` 是创建请求时使用的方法
method: 'get', // 默认是 get // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/', // `transformRequest` 允许在向服务器发送前,修改请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function (data) {
// 对 data 进行任意转换处理 return data;
}], // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对 data 进行任意转换处理 return data;
}], // `headers` 是即将被发送的自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'}, // `params` 是即将与请求一起发送的 URL 参数
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
params: {
ID: 12345
}, // `paramsSerializer` 是一个负责 `params` 序列化的函数
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
}, // `data` 是作为请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: 'Fred'
}, // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeout: 1000, // `withCredentials` 表示跨域请求时是否需要使用凭证
withCredentials: false, // 默认的 // `adapter` 允许自定义处理请求,以使测试更轻松
// 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
adapter: function (config) {
/* ... */
}, // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
// 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
auth: {
username: 'janedoe',
password: 's00pers3cret'
}, // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // 默认的 // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
xsrfCookieName: 'XSRF-TOKEN', // default // `xsrfHeaderName` 是承载 xsrf token 的值的 HTTP 头的名称
xsrfHeaderName: 'X-XSRF-TOKEN', // 默认的 // `onUploadProgress` 允许为上传处理进度事件
onUploadProgress: function (progressEvent) {
// 对原生进度事件的处理
}, // `onDownloadProgress` 允许为下载处理进度事件
onDownloadProgress: function (progressEvent) {
// 对原生进度事件的处理
}, // `maxContentLength` 定义允许的响应内容的最大尺寸
maxContentLength: 2000, // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
validateStatus: function (status) {
return status >= 200 && status < 300; // 默认的
}, // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0,将不会 follow 任何重定向
maxRedirects: 5, // 默认的 // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
// `keepAlive` 默认没有启用
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }), // 'proxy' 定义代理服务器的主机名称和端口
// `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
// 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
proxy: {
host: '127.0.0.1',
port: 9000,
auth: : {
username: 'mikeymike',
password: 'rapunz3l'
}
}, // `cancelToken` 指定用于取消请求的 cancel token
// (查看后面的 Cancellation 这节了解更多)
cancelToken: new CancelToken(function (cancel) {
})
}

axios实例

虽然使用了配置之后不用把参数都写在axios.xxx()里面了,但是这样好像每一次都要定义一个关于请求参数的配置。有些数据我是不想重新定义的,能不能再优化呢?我们可以使用axios实例提前来读取一部分共用配置,然后后续再传入的配置的会与先前的配置进行合并

【下面以提前配置baseUrl,后面的配置传入url为例,如果最终的请求是baseurl和url的拼接结果(通过监听浏览器网络请求得到),那么就说明配置合并成功】

      var instance = axios.create({
baseURL: 'https://www.baidu.com'
})
var request = {
method: 'get',
url: '/s',
params: {wd: 'vue'}
}
// 当传入了url参数的时候,才会发起请求,所以虽然都是传配置,但上面的那个并没有发起请求
instance(request)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})

实现调用自定义函数来发起请求

像上面,我们都是直接调用axios来发起请求的,这可能会导致一些问题,例如在多个组件中都需要发起针对同一个url的请求的时候,如果按照上面直接axios来发起请求的话,那么就会造成代码冗余(想象一下,针对同一个url请求,却要在不同组件中都写一个axios.xxx)。为了减少代码冗余,我们通常都会进行代码抽取,我们把重复的代码都抽取到函数中。

抽取axios请求到函数



上面的例子只是用作演示如何把发起请求的代码抽取到函数中。事实上,上面的抽取并没有完全抽取干净,另一个组件中发起请求时,也要重新定义函数。所以我们要想办法把上面的函数抽取到一个js文件中,抽取到js文件后,我们就可以通过import来导入了。

抽取函数到js文件

首先, 在src下,我们新建一个文件夹api,在api下,我们创建一个index.js【由于一般会有很多个api请求,为了分文件管理api,我们通常会根据api的功能来把发起请求的函数划分到不同的文件中,所以我们可能有时候会创建类似user.js这样命名的文件来存储发起请求的函数。这里由于用于演示,所以命名为index.js】



然后,在index.js中添加下列代码:

import axios from 'axios'

const request = axios.create({
baseURL: 'http://www.xxxx.com'
}) export function getUserList (params) {
return request({
url: '/getuserlist',
method: 'get',
params: params
})
} // 可以有多个export function xxxx

最后,在组件中导入getUserList这个函数,并发起请求:

抽取axios对象到js文件

【如果你有留心的话,你应该感觉到上面的axios对象应该也要进行抽取,因为如果有个js文件的话,会导致创建axios对象的这部分代码赘余了,我们可以把这部分的代码抽取到src/plugin/axios的index.js中】

import axios from 'axios'

const request = axios.create({
baseURL: 'http://www.xxxx.com'
})
export default request // 记得导出

不要忘了,api中也要对应修改:

响应的数据

请求响应后,响应的数据都会封装到response中,其中response.data是服务器返回的响应信息,response.status是响应码,具体如下。

{
// `data` 由服务器提供的响应
data: {}, // `status` 来自服务器响应的 HTTP 状态码
status: 200, // `statusText` 来自服务器响应的 HTTP 状态信息
statusText: 'OK', // `headers` 服务器响应的头
headers: {}, // `config` 是为请求提供的配置信息
config: {}
}

所以请求返回后,我们可以通过response.xxx来获取响应情况。

拦截器

  • 拦截器用于拦截发起的请求或用于拦截返回的响应。
  • 为什么需要拦截器呢?例如,假如某个请求需要带指定的请求头才能请求成功,我们必须要处理一下请求的信息才能够请求成功,这时候我们就可以把请求交给拦截器去处理,使用拦截器来加上请求头是很常见的操作。【加请求头其实我们也可以手动做,为什么要交给拦截器呢?因为拦截器是拦截所有请求,它能给每一个请求都加上头,如果交给我们自己做,那就很累了。】
  • 所以,拦截器可以拦截发起的请求来添加我们需要的数据;拦截器也可以拦截返回的响应,来过滤响应(比如服务器返回的只有一个状态码,那么拦截器可以根据状态码来确认“错误信息”,其实catch(error)中error的原生数据是比较不友好的,所以我们通常都会使用拦截器来“翻译”返回的响应)。

拦截请求

拦截器是基于axios实例来添加的。我们可以使用如下代码来添加一个请求拦截器:

const request = axios.create({
baseURL: 'https://www.xxxx.com'
}) request.interceptors.request.use((config) => { // config是请求的配置
// 这里写在发送请求之前做些什么,我们这里尝试加一个请求头
config.headers['Access-Token'] = '123456'
console.log('发起请求了')
return config
}, (error) => {
// 这里写对请求错误做些什么
return Promise.reject(error)
})

拦截响应

request.interceptors.response.use((response) => {
// 对响应数据做点什么
console.log('请求返回响应了' + response)
return response
}, (error) => {
// 对响应错误做点什么
return Promise.reject(error)
})

补充:


后端开发者的Vue学习之路(五)的更多相关文章

  1. 后端开发者的Vue学习之路(一)

    目录 前言: iview组件库示例 element组件库示例 Vue的介绍 兼容性: 学习Vue需要的前置知识: MVVM模型 补充: 安装/导入 导入Vue 安装 两种方式的区别: HelloWor ...

  2. 后端开发者的Vue学习之路(四)

    目录 上节内容回顾: npm 介绍 安装 常用命令: 补充: 基于npm的Hello World 项目结构分析 用法迁移 小提醒 ES6语法 知识补充 单文件组件 使用注意: 路由 开启路由 定义路由 ...

  3. 后端开发者的Vue学习之路(三)

    目录 上节内容回顾 组件 什么是组件 组件注册 全局注册组件 局部注册组件 使用细节 组件注册的命名规范: 组件中只有一个根元素 组件也是一个实例 组件在某些元素中渲染出错 组件间的数据传递 父子组件 ...

  4. 后端开发者的Vue学习之路(二)

    目录 上篇内容回顾: 数据绑定 表单输入框绑定 单行文本输入框 多行文本输入框 复选框checkbox 单选框radio 选择框select 数据绑定的修饰符 .lazy .number .trim ...

  5. vue学习之路 - 4.基本操作(下)

    vue学习之路 - 4.基本操作(下) 简述:本章节主要介绍 vue 的一些其他常用指令. Vue 指令 这里将 vue 的指令分为系统内部指令(vue 自带指令)和用户自定义指令两种. 系统内部指令 ...

  6. Vue学习之路之登录注册实例代码

    Vue学习之路之登录注册实例代码:https://www.jb51.net/article/118003.htm vue项目中路由验证和相应拦截的使用:https://blog.csdn.net/wa ...

  7. Vue学习之路---No.4(分享心得,欢迎批评指正)

    这里说声抱歉,周末因为有其他事,没有更新博客,那么我们今天继续上周5的说. 老规矩,先回顾一下上一次的重点: 1.利用V-if和v-else来提到show()和hide(),同时要记住,v-else一 ...

  8. Vue学习之路第一篇(学习准备)

    1.开发工具的选择 这个和个人的开发习惯有关,并不做强求,厉害的话用记事本也可以.但是我还是建议用人气比较高的编辑工具,毕竟功能比较全面,开发起来效率比较高. 我之前写前端一直用的是sublimete ...

  9. Vue学习之路第十五篇:v-if和v-show指令

    1.v-if和v-show都是用来实现条件判断的指令. 2.先看代码 <body> <div id="app"> <button @click=&qu ...

随机推荐

  1. DB2 数据库的安装配置及监控

    一.DB2简介 IBM公司研制的一种关系型数据库系统.DB2主要应用于大型应用系统,具有较好的可伸缩性,可支持从大型机到单用户环境,应用于OS/2.Windows等平台下. DB2提供了高层次的数据利 ...

  2. 前端基础之JS

    流程控制 if-else var a = 10; if (a > 5){ console.log("yes"); }else { console.log("no&q ...

  3. EF Core中避免贫血模型的三种行之有效的方法(翻译)

    Paul Hiles: 3 ways to avoid an anemic domain model in EF Core 1.引言 在使用ORM中(比如Entity Framework)贫血领域模型 ...

  4. 【XSS】利用 onload 事件监控流量劫持

    说到跨站资源监控,首先会联想到『Content Security Policy』.既然 CSP 好用,我们何必自己再搞一套呢.那就先来吐槽下 CSP 的缺陷. 目前的 CSP 日志不详细 用过 CSP ...

  5. 企业IT管理员IE11升级指南【12】—— 兼容视图列表介绍

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  6. spring boot - 整合jpa多对对关系保存和查询示例

    pojo: package com.example.zs.springDataJpa; import org.hibernate.annotations.Proxy; import javax.per ...

  7. pytthon—day8 读写模式的结合、文件操作模式、with完成文本文件复制、游标操作

    一.读写模式的结合 w:写指没有新建文件,有文件就清空 w=open('1.txt','w',encoding='utf-8') w.write('000\n') 在写入数据时,需要及时处理内存空间, ...

  8. K60平台智能车开发工作随手记

    (图片仅为示例,并不一定固定为这种造型) 第十二届全国大学生智能汽车竞赛有一个分项是光电四轮车的竞速(任务A),Seven她们组采购到的配件使用了freescale Crotex-M4内核的CPU,T ...

  9. Lucene 09 - 什么是Lucene的高亮显示 + Java API实现高亮显示

    目录 1 什么是高亮显示 2 高亮显示实现 2.1 配置pom.xml文件, 加入高亮显示支持 2.2 代码实现 2.3 自定义html标签高亮显示 1 什么是高亮显示 高亮显示是全文检索的一个特点, ...

  10. PHP自动加载机制

    类的载入共经历了三个阶段 第一阶段是面向过程式的做法,整个项目里到处都是include或require. 问题:难看,不易维护. . 第二阶段是魔术方法__autoload,当new一个类的时候,如果 ...