vue实践---vue结合 promise 封装原生ajax

ⅰ亾dé卋堺 提交于 2020-03-16 03:46:56

有时候不想使用axios这样的外部依赖,想自己封装ajax,这里有两种方法

方法一,在单个页面内使用

封装的代码如下:

 beforeCreate () {
      this.$http = (() => {
        let createFetch = (type, url, params) => {
          return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest()
            xhr.onreadystatechange = () => {
              if (xhr.readyState === 4){
                if(xhr.status === 200){
                  var res = xhr.responseText;
                  try {
                      res = JSON.parse(xhr.responseText)
                  } catch (e) {}
                  resolve(res)
                } else {
                  reject(xhr.responseText)
                }
              }
            }
            url += url.includes('?') ? '&' : '?'
  
            if (type === 'GET') {
              let serialArr = []
              Object.keys(params).forEach(v => {
               serialArr.push(`${v}=${params[v]}`)
              })
              url += serialArr.join('&')
            }
            xhr.withCredentials = true; //支持跨域发送cookies
            xhr.open(type, url, true);
            xhr.send(type === 'GET' ? null : params);
          })
        }
        return {
          get: (...args) => createFetch("GET", args[0], args[1]),
          post: (...args) => createFetch("POST", args[0], args[1])
        }
      })()
    }

使用的代码如下:

this.$http.get('http://123.103.9.204:6058/official/rest/document/wenku/1/3293036/groupList', {pageSize: '1', pageSize: 30, groupType: 0}).then((res)=>{
            if(res.flag == 0){
                this.requestData = res.data
            }
        })

 

方法二,全局注册

封装的方法如下:

export default
{
    install(Vue)
    {
        Vue.prototype.$http=function(options){
            /*将数据转化为字符串*/
            var strData=function(data){
                var dataStr="";
                for(var key in data){
                    dataStr += key+'='+data[key]+'&';
                }
                dataStr = dataStr && dataStr.slice(0,-1);
                return dataStr;
            };
            /*创建 XMLHttpRequest 对象*/
            var createXHR=function(){
                var xhr;
                if (window.XMLHttpRequest)
                {// code for IE7+, Firefox, Chrome, Opera, Safari
                    xhr=new XMLHttpRequest();
                }
                else {// code for IE6, IE5
                    xhr=new ActiveXObject("Microsoft.XMLHTTP");
                }
                return xhr
            };
            /*向服务器发送请求*/
            var open=function(xhr,type,url,async){
                xhr.open(type,url,async);
            };
            var send=function(xhr,msg){
                xhr.send(msg);
            };
            var setHeaders=function(xhr,headers){
                xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                if(!headers){
                    return false;
                }
                for(var key in headers){
                    xhr.setRequestHeader(key,headers[key]);
                }
            }
            var request=function(xhr,opts){
                if(opts.type==="GET"){
                    open(xhr,opts.type,opts.url+'?'+strData(opts.data),opts.async);
                    send(xhr,null);
                }
                else if(opts.type==="POST"){
                    open(xhr,opts.type,opts.url,opts.async);
                    if(opts.headers){
                        setHeaders(xhr,opts.headers);
                    }
                    send(xhr,strData(opts.data));
                }
            };
            return new Promise((resolve,reject)=>{
                if(!options || typeof options != 'object'){
                    reject(new Error("参数错误,请传入对象参数!"));
                    return false;
                }
                if(!options.url){
                    reject(new Error("url不能为空"));
                    return false;
                }
                options.type = options.type?options.type.toUpperCase():'GET';
                options.async = (options.async && options.async === false)?false:true;
                options.dataType = options.dataType || "json";
                options.data = options.data || {};
                options.headers = options.headers || {};
                var dataStr=strData(options.data);
                /*创建 XMLHttpRequest 对象*/
                var xhr=createXHR();
                /*创建服务器返回响应后执行操作函数*/
                xhr.onreadystatechange=function(){
                    var responseData;
                    if(xhr.readyState == 4){
                        switch  (xhr.status){
                            case 200:
                                switch (options.dataType){
                                    case "xml":
                                        responseData=xhr.responseXML;
                                        break;
                                    case "text":
                                        responseData = xhr.responseText;
                                        break;
                                    case "json":
                                        responseData = JSON.parse(xhr.responseText);
                                        break;
                                }
                                resolve(responseData);
                            default:
                                reject(new Error("这里做错误处理"));
                        }
                    }
                };
                /*向服务器发送请求*/
                request(xhr,options);
            })
        };
        Vue.prototype.$post=function(options){
            options.type='post';
            return this.$http(options);
        };
        Vue.prototype.$get=function(options){
            options.type='get';
            return this.$http(options);
        };
    }
}
import Vue from 'vue'
import App from './App.vue'
import router from './router'

import Install from './install/index.js'// 这里全局安装
Vue.use(Install)

new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

使用的代码如下:

            var reuestData = {
                url: "http://123.103.9.204:6058/official/rest/document/wenku/1/3293036/groupList",
                data:  {pageSize: '1', pageSize: 30, groupType: 0}
            }
            this.$get(reuestData).then((res)=>{
                if(res.flag == 0) {
                    this.requestData = res.data
                }
            })

两种方法的比较:

方法一的每个页面要想使用, 都需要写相关的代码,而且由于使用了匿名函数立即执行,如果函数内部有错误,不好调试

方法二使用了全局注册,只要在main.js 注册了全局都可以使用。

 

具体的代码可以看这里: https://github.com/YalongYan/vue-practice/tree/master/vue-native-ajax

vue实践系列请看这里: https://github.com/YalongYan/vue-practice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!