需求分析

  因为有时候想提高性能,只需要一个ajax函数,不想引入较大的jq文件,尝试过axios,可是get方法不支持多层嵌套的json,post方式后台接收方式似乎要变。。也许是我不太会用吧。。其实换个方式接收也没什么,只是习惯了JQ序列化参数。所以上网搜集了很多资料,同时也进一步了解了一点JQ。以下代码很多来自于网上,自己整合了一下。

 

封装代码

 

  1 /**
  2  * @Description: 模仿jQuery封装简单的ajax功能。
  3  * @Author: kill370354@qq.com
  4  **/
  5 
  6 var Ajax = {};
  7 (function($) {
  8     function ajax(options) {
  9         var str;
 10         var xmlHttpRequest;
 11         var timer;
 12         if (window.XMLHttpRequest) {
 13             xmlHttpRequest = new XMLHttpRequest();
 14         } else {
 15             xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
 16         }
 17 
 18         var source = {
 19             type: "GET",
 20             processData: true,
 21             contentType: "application/x-www-form-urlencoded"
 22         };
 23         options = mergeObject(source, options);
 24         if (options.contentType.replace(/(^\s*)|(\s*$)/g, "") === "application/json") {
 25             options.processData = false;
 26         }
 27         xmlHttpRequest = mergeObject(xmlHttpRequest, options.xhrFields);
 28         if (options.type.toUpperCase() === "GET") {
 29             str = param(mergeObject(urlorQuerytoObject(options.url), options.data));
 30             if (options.url.indexOf("?") !== -1) {
 31                 options.url = options.url.substr(0, options.url.indexOf("?"));
 32             }
 33             xmlHttpRequest.open("GET", options.url + "?" + str, true);
 34             xmlHttpRequest.send(null);
 35         } else {
 36             xmlHttpRequest.open(options.type.toUpperCase(), options.url, true);
 37             xmlHttpRequest.setRequestHeader("Content-type", options.contentType);
 38             if (options.processData) {
 39                 str = param(options.data);
 40             } else {
 41                 str = options.data;
 42             }
 43             xmlHttpRequest.send(str);
 44         }
 45         xmlHttpRequest.onreadystatechange = function() {
 46             var textStatus = "";
 47             if (xmlHttpRequest.readyState === 4) {
 48                 clearInterval(timer);
 49                 if ((xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) || xmlHttpRequest.status === 304) {
 50                     if (xmlHttpRequest.status === 304) {
 51                         textStatus = "notmodified";
 52                     } else {
 53                         textStatus = "success";
 54                     }
 55                     try {
 56                         // 如果是JSON格式,自动转换为JSON对象
 57                         options.success(JSON.parse(xmlHttpRequest.responseText), textStatus);
 58                     } catch (e) {
 59                         options.success(xmlHttpRequest.responseText, textStatus);
 60                     }
 61                 } else {
 62                     textStatus = "error";
 63                     if (typeof options.error === "function") {
 64                         options.error(xmlHttpRequest, textStatus);
 65                     }
 66                 }
 67                 if (typeof options.complete === "function") {
 68                     options.complete(xmlHttpRequest, textStatus);
 69                 }
 70             }
 71         };
 72         //判断是否超时
 73         if (typeof options.timeout === "number") {
 74             timer = setTimeout(function() {
 75                 if (typeof options.error === "function") {
 76                     options.error(xmlHttpRequest, "timeout");
 77                     options.complete(xmlHttpRequest, "timeout");
 78                 }
 79                 if (typeof options.complete === "function") {
 80                     options.complete(xmlHttpRequest, "timeout");
 81                 }
 82                 xmlHttpRequest.abort();
 83             }, options.timeout);
 84         }
 85     }
 86 
 87     // 合并对象
 88     function mergeObject(target) {
 89         if (target == null) {
 90             throw new TypeError("Cannot convert undefined or null to object");
 91         }
 92         target = Object(target);
 93         for (var index = 1; index < arguments.length; index++) {
 94             var source = arguments[index];
 95             if (source != null) {
 96                 for (var key in source) {
 97                     if (Object.prototype.hasOwnProperty.call(source, key)) {
 98                         target[key] = source[key];
 99                     }
100                 }
101             }
102         }
103         return target;
104     }
105 
106     // 把url中的查询字符串转为对象,主要是想当方式为get时,用data对象的参数覆盖掉url中的参数
107     function urlorQuerytoObject(urlorQuery) {
108         var queryArr = [];
109         var urlSplit = urlorQuery.split("?");
110         queryArr[0] = urlSplit[0];
111         if (urlSplit[1]) {
112             queryArr[0] = urlSplit[1];
113         }
114         queryArr = queryArr[0].split("&");
115         var obj = {};
116         var i = 0;
117         var temp;
118         var key;
119         var value;
120         while (i < queryArr.length) {
121             temp = queryArr[i].split("=");
122             key = temp[0];
123             value = temp[1];
124             obj[key] = value;
125             i++;
126         }
127         return obj;
128     }
129 
130     // 序列化参数
131     // 转载自 https://www.jianshu.com/p/0ca22d53feea
132     function param(obj, traditional) {
133         if (traditional === "undefined") {
134             traditional = false;
135         }
136         var rbracket = /\[\]$/,
137             op = Object.prototype,
138             ap = Array.prototype,
139             aeach = ap.forEach,
140             ostring = op.toString;
141 
142         function isFunction(it) {
143             return ostring.call(it) === "[object Function]";
144         }
145 
146         function isArray(it) {
147             return ostring.call(it) === "[object Array]";
148         }
149 
150         function isObject(it) {
151             return ostring.call(it) === "[object Object]";
152         }
153 
154         function buildParams(prefix, obj, traditional, add) {
155             var name;
156             if (isArray(obj)) {
157                 // Serialize array item.
158                 aeach.call(obj, function(v, i) {
159                     if (traditional || rbracket.test(prefix)) {
160                         // Treat each array item as a scalar.
161                         add(prefix, v);
162                     } else {
163                         // Item is non-scalar (array or object), encode its numeric index.
164                         buildParams(
165                             prefix + "[" + (typeof v === "object" && v != null ? i : "") + "]",
166                             v,
167                             traditional,
168                             add
169                         );
170                     }
171                 });
172             } else if (!traditional && isObject(obj)) {
173                 // Serialize object item.
174                 for (name in obj) {
175                     buildParams(prefix + "[" + name + "]", obj[name], traditional, add);
176                 }
177             } else {
178                 // Serialize scalar item.
179                 add(prefix, obj);
180             }
181         }
182 
183         // Serialize an array of form elements or a set of
184         // key/values into a query string
185         function jollyparam(a, traditional) {
186             var prefix,
187                 s = [],
188                 add = function(key, valueOrFunction) {
189                     // If value is a function, invoke it and use its return value
190                     var value = isFunction(valueOrFunction) ? valueOrFunction() : valueOrFunction;
191                     s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value == null ? "" : value);
192                 };
193             // If an array was passed in, assume that it is an array of form elements.
194             if (isArray(a)) {
195                 // Serialize the form elements
196                 aeach.call(a, function(item) {
197                     add(item.name, item.value);
198                 });
199             } else {
200                 // If traditional, encode the "old" way (the way 1.3.2 or older
201                 // did it), otherwise encode params recursively.
202                 for (prefix in a) {
203                     buildParams(prefix, a[prefix], traditional, add);
204                 }
205             }
206             // Return the resulting serialization
207             return s.join("&");
208         }
209 
210         return jollyparam(obj, traditional);
211     }
212 
213     $ = {
214         get: function(url, data, success) {
215             return ajax({ url: url, data: data, success: success });
216         },
217         post: function(url, data, success) {
218             return ajax({
219                 type: "POST",
220                 url: url,
221                 data: data,
222                 success: success
223             });
224         },
225         ajax: ajax,
226         param: param,
227         urlorQuerytoObject: urlorQuerytoObject,
228         mergeObject: mergeObject
229     };
230 
231     // 满足 JQuery 的使用习惯
232     if (typeof window.$ === "undefined") {
233         window.$ = $;
234     }
235 })(Ajax);
View Code

 

用法


高度模仿JQ。

 1 // get请求
 2 $.get("", {}, function(data) {});
 3 
 4 // post请求
 5 $.post("", {}, function(data) {});
 6 
 7 // 更完整的ajax
 8 $.ajax({
 9     type: "post", // 非必须,默认 get
10     url: "",
11     data: {  },
12     xhrFields: {
13     // 非必须,自定义 XHR 对象属性
14         withCredentials: true
15     },
16     processData: true, // 非必须,默认 true
17     contentType: "application/x-www-form-urlencoded", // 非必须,默认 application/x-www-form-urlencoded
18     success: function(responseData, textStatus) {
19         // textStatus : "success"、"notmodified"
20     },
21     // timeout: 1, // 非必须,超时毫秒数,如果设置了,超时且存在error函数则会调用
22     error: function(xhr, textStatus) {
23         // 非必须
24         // textStatus: "error"、"timeout"
25     },
26     complete: function(xhr, textStatus) {
27         // 非必须,无论成败最后均调用
28         // textStatus:  "success"、"notmodified"、"error"、"timeout"
29     }
30 });
View Code

 

注意事项


1. 如果 " $ " 符号不能使用,请用 " Ajax " 替代,这个变量名若仍有冲突,请修改源代码首尾两行。

2. 如果返回的是json格式的字符串,会自动将字符串转为json对象传给success函数参数,其他情况均为字符串。

 

 

  第一次发博客,经验不足,引用了许多别人的代码,只是这功能已经缠了我很多天了,今天终于相对完善了,如有不妥,还请多多指教!

 github