模仿JQuery封装ajax功能
程序员文章站
2022-07-09 20:40:58
需求分析 因为有时候想提高性能,只需要一个ajax函数,不想引入较大的jq文件,尝试过axios,可是get方法不支持多层嵌套的json,post方式后台接收方式似乎要变。。也许是我不太会用吧。。其实换个方式接收也没什么,只是习惯了JQ序列化参数。所以上网搜集了很多资料,同时也进一步了解了一点JQ。 ......
需求分析
因为有时候想提高性能,只需要一个ajax函数,不想引入较大的jq文件,尝试过axios,可是get方法不支持多层嵌套的json,post方式后台接收方式似乎要变。。也许是我不太会用吧。。其实换个方式接收也没什么,只是习惯了jq序列化参数。所以上网搜集了很多资料,同时也进一步了解了一点jq。以下代码很多来自于网上,自己整合了一下。
封装代码
1 var ajax = {}; 2 (function($) { 3 4 function ajax(options) { 5 var str; 6 var xmlhttprequest; 7 var timer; 8 if (window.xmlhttprequest) { 9 xmlhttprequest = new xmlhttprequest(); 10 } else { 11 xmlhttprequest = new activexobject("microsoft.xmlhttp"); 12 } 13 options = object.assign({}, { type: "get", processdata: true, contenttype: "application/x-www-form-urlencoded" }, options); 14 if (options.type.touppercase() !== "get") { 15 xmlhttprequest.open(options.type.touppercase(), options.url, true); 16 xmlhttprequest.setrequestheader("content-type", options.contenttype); 17 if (options.processdata) { 18 str = param(options.data); 19 } else { 20 str = options.data; 21 } 22 xmlhttprequest.send(str); 23 } else { 24 str = param(object.assign(urlorquerytoobject(options.url), options.data)); 25 if (options.url.indexof("?") !== -1) { 26 options.url = options.url.substr(0, options.url.indexof("?")); 27 } 28 xmlhttprequest.open("get", options.url + "?" + str, true); 29 xmlhttprequest.send(null); 30 } 31 xmlhttprequest.onreadystatechange = function() { 32 if (xmlhttprequest.readystate === 4) { 33 clearinterval(timer); 34 if (xmlhttprequest.status === 200) { 35 try { 36 // 如果是json格式,自动转换为json对象 37 options.success(json.parse(xmlhttprequest.responsetext)); 38 } catch (e) { 39 options.success(xmlhttprequest.responsetext); 40 } 41 } else if (options.error) { 42 if (xmlhttprequest.status === 304) { 43 options.error(xmlhttprequest, "notmodified"); 44 } else { 45 options.error(xmlhttprequest, xmlhttprequest.statustext); 46 } 47 } 48 } 49 }; 50 //判断是否超时 51 if (options.timeout) { 52 timer = settimeout(function() { 53 if (options.error) { 54 options.error(xmlhttprequest, "timeout"); 55 } 56 xmlhttprequest.abort(); 57 }, options.timeout); 58 } 59 } 60 61 // 把url中的查询字符串转为对象,主要是想当方式为get时,用data对象的参数覆盖掉url中的参数 62 function urlorquerytoobject(urlorquery) { 63 var queryarr = []; 64 var urlsplit = urlorquery.split("?"); 65 queryarr[0] = urlsplit[0]; 66 if (urlsplit[1]) { 67 queryarr[0] = urlsplit[1]; 68 } 69 queryarr = queryarr[0].split("&"); 70 var obj = {}; 71 var i = 0; 72 var temp; 73 var key; 74 var value; 75 for (i = 0; i < queryarr.length; i += 1) { 76 temp = queryarr[i].split("="); 77 key = temp[0]; 78 value = temp[1]; 79 obj[key] = value; 80 } 81 return obj; 82 } 83 84 // 序列化参数 85 // 转载自 https://www.jianshu.com/p/0ca22d53feea 86 function param(obj, traditional) { 87 88 if (traditional === "undefined") { traditional = false; } 89 var 90 rbracket = /\[\]$/, 91 op = object.prototype, 92 ap = array.prototype, 93 aeach = ap.foreach, 94 ostring = op.tostring; 95 96 function isfunction(it) { 97 return ostring.call(it) === "[object function]"; 98 } 99 100 function isarray(it) { 101 return ostring.call(it) === "[object array]"; 102 } 103 104 function isobject(it) { 105 return ostring.call(it) === "[object object]"; 106 } 107 108 function buildparams(prefix, obj, traditional, add) { 109 var name; 110 if (isarray(obj)) { 111 // serialize array item. 112 aeach.call(obj, function(v, i) { 113 if (traditional || rbracket.test(prefix)) { 114 // treat each array item as a scalar. 115 add(prefix, v); 116 } else { 117 // item is non-scalar (array or object), encode its numeric index. 118 buildparams( 119 prefix + "[" + (typeof v === "object" && v != null ? i : "") + "]", 120 v, 121 traditional, 122 add 123 ); 124 } 125 }); 126 } else if (!traditional && isobject(obj)) { 127 // serialize object item. 128 for (name in obj) { 129 buildparams(prefix + "[" + name + "]", obj[name], traditional, add); 130 } 131 } else { 132 // serialize scalar item. 133 add(prefix, obj); 134 } 135 } 136 // serialize an array of form elements or a set of 137 // key/values into a query string 138 function jollyparam(a, traditional) { 139 var prefix, 140 s = [], 141 add = function(key, valueorfunction) { 142 // if value is a function, invoke it and use its return value 143 var value = isfunction(valueorfunction) ? valueorfunction() : valueorfunction; 144 s[s.length] = encodeuricomponent(key) + "=" + 145 encodeuricomponent(value == null ? "" : value); 146 }; 147 // if an array was passed in, assume that it is an array of form elements. 148 if (isarray(a)) { 149 // serialize the form elements 150 aeach.call(a, function(item) { 151 add(item.name, item.value); 152 }); 153 } else { 154 // if traditional, encode the "old" way (the way 1.3.2 or older 155 // did it), otherwise encode params recursively. 156 for (prefix in a) { 157 buildparams(prefix, a[prefix], traditional, add); 158 } 159 } 160 // return the resulting serialization 161 return s.join("&"); 162 } 163 return jollyparam(obj, traditional); 164 } 165 166 // 为避免 object.assign 不能使用 167 // 转载自 https://developer.mozilla.org/zh-cn/docs/web/javascript/reference/global_objects/object/assign 168 if (typeof object.assign != "function") { 169 // must be writable: true, enumerable: false, configurable: true 170 object.defineproperty(object, "assign", { 171 value: function assign(target, varargs) { // .length of function is 2 172 "use strict"; 173 if (target == null) { // typeerror if undefined or null 174 throw new typeerror("cannot convert undefined or null to object"); 175 } 176 var to = object(target); 177 for (var index = 1; index < arguments.length; index++) { 178 var nextsource = arguments[index]; 179 if (nextsource != null) { // skip over if undefined or null 180 for (var nextkey in nextsource) { 181 // avoid bugs when hasownproperty is shadowed 182 if (object.prototype.hasownproperty.call(nextsource, nextkey)) { 183 to[nextkey] = nextsource[nextkey]; 184 } 185 } 186 } 187 } 188 return to; 189 }, 190 writable: true, 191 configurable: true 192 }); 193 } 194 195 $ = { 196 get: function(url, data, success) { 197 return ajax({ url: url, data: data, success: success }); 198 }, 199 post: function(url, data, success) { 200 return ajax({ type: "post", url: url, data: data, success: success }); 201 }, 202 ajax: function(options) { return ajax(options); }, 203 param: function(obj, traditional) { return param(obj, traditional); }, 204 urlorquerytoobject: function(urlorquery) { return urlorquerytoobject(urlorquery); } 205 }; 206 207 // 满足 jquery 的使用习惯 208 if (typeof window.$ === "undefined") { 209 window.$ = $; 210 } 211 })(ajax);
用法
高度模仿jq。
1 // get请求 2 $.get("", {}, function(data) {}) 3 4 // post请求 5 $.post("", {}, function(data) {}) 6 7 // 更完整的ajax 8 $.ajax({ 9 type: "post", 10 // 非必须,默认 get 11 url: "", 12 data: {}, 13 // json格式 14 processdata: true, 15 // 非必须,默认 true 16 contenttype: "application/json;charsetset=utf-8", 17 //非必须,默认 application/x-www-form-urlencoded 18 success: function(data) {}, 19 timeout: 1000, 20 // 超时时间,非必须,如果设置了,超时且存在error函数则会调用 21 error: function(xhr, statustext) {// 非必须 22 // statustext: "notmodified","timeout", 或者其他xmlhttprequest.statustext 23 } 24 });
注意事项
1. 如果 " $ " 符号不能使用,请用 " ajax " 替代,这个变量名若仍有冲突,请修改源代码首尾两行。
2. 如果返回的是json格式的字符串,会自动将字符串转为json对象传给success函数参数,其他情况均为字符串。
第一次发博客,经验不足,引用了许多别人的代码,只是这功能已经缠了我很多天了,今天终于相对完善了,如有不妥,还请多多指教!