Vue2全家桶之三:vue-resource(不推荐)----axios(推荐)

这是我第8篇简书。

这篇文章去年5月就写了,还差一点没收尾,觉得写的不好放在日记本里没发布,今天就发了吧,重点看我axios的那个长长的例子。初学者如果看不懂私信我吧。。有错误也请大佬拍砖,毕竟我已经心不在焉的去考公了,做项目只想完成功能就算了,心不在这里啊。。。

vue-resource早已不再更新!尤大大推荐用axios!!
这里还是先简单说一下vue-resource。

  vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应。也就是说,Ajax能做的事情,vue-resource插件一样也能做到,而且vue-resource的API更为简洁。划重点,vue-resource还提供了非常有用的inteceptor(拦截器)功能(经常使用),使用inteceptor可以在请求发送前和发送请求后做一些处理,比如使用inteceptor在ajax请求时显示loading界面,或者在请求发送前在headers中设置token,加入token验证,拦截器在axios中详细介绍。

一、简单介绍vue-resource用法

1.引入
import Vue from 'vue'
import VueResource from 'vue-resource'
Vue.use(VueResource)
2.使用

引入vue-resource后,可以基于全局的Vue对象使用http,也可以基于某个Vue实例使用http。

在一个Vue实例内使用$http
this.$http.get('/Url', [options]).then((response) => {
    // 响应成功回调
}, (response) => {
    // 响应错误回调
});
3.跨域

解决vue-resource post请求跨域问题:
vue提供了一个简单的解决方法,就是 Vue.http.options.emulateJSON = true 其实等同于在headers中添加 'Content-Type': 'application/x-www-form-urlencoded'。

注意:$http请求和jquery中使用ajax还是有点区别,这里的post的data默认不是以form data的形式,而是request payload。所以你们别忘了将emulateJSON 属性设置为true,即可解决这个问题。Vue.http.options.emulateJSON = true

form data和request payload的区别:

  • form date
    get请求,是将请求参数以&方法,拼接在url后面,如:http://www.dxl.com?name=dxl&password=8888;
    真正可以明显看出区分的是在post请求上,
    post请求时,头文件 中Content-Type 是默认值 application/x-www-form-urlencoded,参数是放在 form date中的。
  • request payload
    post请求时,头文件 中Content-Type 是默认值 application/json;charset=UTF-8,参数是放在 request payload 中的。
JSONP请求:
getJsonp: function() {
    this.$http.jsonp(this.apiUrl).then(function(response){
        this.$set('gridData', response.data)
    })
}
4.resource服务

vue-resource提供了另外一种方式访问HTTP——resource服务
resource对象也有两种访问方式:
全局访问:Vue.resource
实例访问:this.$resource

(1)get请求

getCustomers: function() {

    var resource = this.$resource(this.apiUrl)
        vm = this

    resource.get()
        .then((response) => {
            vm.$set('gridData', response.data)
        })
        .catch(function(response) {
            console.log(response)
        })
}

(2)post请求
使用save方法发送POST请求。

createCustomer: function() {
    var resource = this.$resource(this.apiUrl)
        vm = this
        
    resource.save(vm.apiUrl, vm.item)
        .then((response) => {
            vm.$set('item', {})
            vm.getCustomers()
        })
    this.show = false
}

(3)使用update方法发送PUT请求,使用remove或delete方法发送DELETE请求

5.拦截器interceptors
Vue.http.interceptors.push((request, next) => {
        // ...
        // 请求发送前的处理逻辑
        // ...
    next((response) => {
        // ...
        // 请求发送后的处理逻辑
        // ...
        // 根据请求的状态,response参数会返回给successCallback或errorCallback
        return response
    })
})

二、axios

1.介绍

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
看这个吧,传送门→https://www.kancloud.cn/yunye/axios/234845
axios支持IE8。

它可以:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

(1)get请求

axios.get('/user', {
    params: {
      ID: 1111
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// 还可以这么写,es7新特性async/await 
async function getUser() {
  try {
    const response = await axios.get('/user?ID=1111');
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}

*async用于声明一个函数是异步的,而await是“等待”的意思,就是用于等待异步完成。
await只能在async函数中使用。
await可以让js进行等待,直到一个promise执行并返回它的结果,js才会继续往下执行。
async/await 面试经常问到哦,百度查一下,划重点

(2)post请求

axios.post('/user', {
    firstName: 'xiliDong',
    lastName: 'dongxili'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
//或者这样写
axios({
  method: 'post',
  url: '/user',
  data: {
    firstName: 'xiliDong',
    lastName: 'dongxili'
  }
});

(3)执行多个并发请求

function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // 两个请求现在都执行完成
  }));
2.创建实例(重点)

可以使用自定义配置新建一个 axios 实例

axios.create([config])
var instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});
(1)响应结构:
{
  data: {},    // data由服务器提供的响应
  status: 200,  // 服务器响应的 HTTP 状态码
  statusText: 'OK',   // 服务器响应的 HTTP 状态信息
  headers: {},    // 服务器响应的头
  config: {}     // 为请求提供的配置信息
}

使用 then 时,你将接收下面这样的响应:
axios.get('/user/1111')
  .then(function(response) {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
  });
(2)指定配置的默认值:
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
  • 自定义实例默认值:
// 创建实例时设置配置的默认值
var instance = axios.create({
  baseURL: 'https://api.example.com'
});
// 在实例已创建后修改默认值
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
(3)拦截器:

(axios配置看我这个例子就差不多了)

// request拦截器
import axios from 'axios'
import router from '../router'
// 创建axios实例
const service = axios.create({
  timeout: null // 请求超时时间
})
let serviceTips = '服务器超时'

// request拦截器
service.interceptors.request.use(
  config => {
    // console.log(service.interceptors)
    // 获取本地token
    let token = localStorage.getItem('tokendata')
    // 设置请求头
    let headers = 'application/json'
    // 是否携带token
    let tokenFlag = true
    // 是否修改请求信息
    if (config.opts) {
      // 获取携带token状态
      tokenFlag = config.opts ? config.opts.token : true
      // 获取请求头
      headers = config.opts.Header ? config.opts.Header : 'application/json'
      // 拓展头部参数
      let Head = config.opts.Head
      if (Head) {
        for (let key in Head) {
          config.headers[key] = Head[key]
        }
      }
    }
    // 暂时不加入token验证
    // if (token && tokenFlag) {
    //   // 条件允许,携带token请求
    //   config.headers['JSESSIONID'] = token
    //   // config.headers['X-Auth0-Token'] = token
    // } else {
    //   headers = 'application/x-www-form-urlencoded'
    // }
    // 设置请求格式
    config.headers['Content-Type'] = headers
    return config
  },
  err => {
    return Promise.reject(err)
  }
)

// http response 服务器响应拦截器
service.interceptors.response.use(
  response => {
    return response
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          error.response.data = '登陆超时,重新登陆'
          router.replace({
            path: '/login',
            query: {
              redirect: router.currentRoute.fullPath
            } // 登录成功后跳入浏览的当前页面
          })
          break
        case 404:
          error.response.data = '资源不存在'
          break
        case 406:
          error.response.data = '头部无携带token'
          break
        case 412:
          // 拦截错误 并重新跳入登页重新获取token
          router.replace({
            path: '/login',
            query: {
              redirect: router.currentRoute.fullPath
            } // 登录成功后跳入浏览的当前页面
          })
          error.response.data = '秘钥失效'
          localStorage.removeItem('tokendata') // 清除token
          break
        case 415:
          error.response.data = '请求type有误'
          break
        case 500:
          error.response.data = '服务器异常'
          break
      }
      serviceTips = error.response.data
    }
    Message.error(serviceTips)
    return Promise.reject(serviceTips)
  }
)
export default service
 配置好了怎么使用呢?

在api.js中引入拦截器:
import fetch from '@/utils/fetch' // 拦截器
export function getList(obj) {
  const data = obj
  return fetch({
    url:  '',
    method: 'POST',
    data
  })
}

--------------------------------
可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围。
export function getList(obj) {
  const data = obj
  return fetch({
    url:  '',
    method: 'POST',
    validateStatus: function(status) {
      // return status >= 200 && status < 300; // 默认的
      return status < 500; // 状态码在大于或等于500时才会 reject
    },
    data
  })
}
重点:
axios的请求头默认为'application/json',
即axios会默认序列化 JavaScript 对象为 JSON. 
如果想使用 application/x-www-form-urlencoded 格式,你可以使用下面的配置:
import Qs from 'qs'

export function getList(obj) {
  const data = Qs.stringify(obj)
  return fetch({
    url:  '',
    method: 'POST',
    headers: {
      'content-type': 'application/x-www-form-urlencoded',
       // 如果需要XMLHttpRequest,加入这个
       'X-Requested-With': 'XMLHttpRequest'
    },
    data
  })
}


然后在在vue文件中引入此函数来获取数据
// param为前端传入的参数
getList(param).then(res => {
  if (res.data.code === 0) {
    console.log(res.data.data);
    this.allOrderTable = res.data.data.data;
    this.pageTotal = res.data.data.total;
  } else {
    this.$message({
      message: `[${res.data.msg}]:查询失败`,
      type: "error"
    });
  }
  this.listLoading = false;
})
.catch(() => {})

如果你想在稍后移除拦截器,可以这样:

var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
(4)使用 cancel token 取消请求:

(额,我好像没用到过(4))
可以使用 CancelToken.source 工厂方法创建 cancel token

var CancelToken = axios.CancelToken;
var source = CancelToken.source();

axios.get('/user/1111', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

还可以通过传递一个 executor 函数到 CancelToken
的构造函数来创建 cancel token:

var CancelToken = axios.CancelToken;
var cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  })
});

// 取消请求
cancel();

注意,还可以使用同一个 cancel token 取消多个请求
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,406评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,976评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,302评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,366评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,372评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,457评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,872评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,521评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,717评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,523评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,590评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,299评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,859评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,883评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,127评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,760评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,290评论 2 342

推荐阅读更多精彩内容