需求分析
因为有时候想提高性能,只需要一个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);
用法
高度模仿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 });
注意事项
1. 如果 " $ " 符号不能使用,请用 " Ajax " 替代,这个变量名若仍有冲突,请修改源代码首尾两行。
2. 如果返回的是json格式的字符串,会自动将字符串转为json对象传给success函数参数,其他情况均为字符串。
第一次发博客,经验不足,引用了许多别人的代码,只是这功能已经缠了我很多天了,今天终于相对完善了,如有不妥,还请多多指教!