美文网首页IT@程序员猿媛让前端飞码农的世界
Vue2全家桶之三:vue-resource(不推荐)----a

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

作者: 东西里 | 来源:发表于2019-04-02 20:21 被阅读6次

    这是我第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 取消多个请求
    

    相关文章

      网友评论

        本文标题:Vue2全家桶之三:vue-resource(不推荐)----a

        本文链接:https://www.haomeiwen.com/subject/tkeedftx.html