vue實踐---vue結合 promise 封裝原生ajax


有時候不想使用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM