模仿JQuery封装ajax功能

1 篇文章 0 订阅

需求分析

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

 

封装代码

/**
 * @Description: 模仿jQuery封装简单的ajax功能。
 * @Author: kill370354@qq.com
 **/

var Ajax = {};
(function($) {
    function ajax(options) {
        var str;
        var xmlHttpRequest;
        var timer;
        if (window.XMLHttpRequest) {
            xmlHttpRequest = new XMLHttpRequest();
        } else {
            xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }

        var source = {
            type: "GET",
            processData: true,
            contentType: "application/x-www-form-urlencoded"
        };
        options = mergeObject(source, options);
        if (options.contentType.replace(/(^\s*)|(\s*$)/g, "") === "application/json") {
            options.processData = false;
        }
        xmlHttpRequest = mergeObject(xmlHttpRequest, options.xhrFields);
        if (options.type.toUpperCase() === "GET") {
            str = param(mergeObject(urlorQuerytoObject(options.url), options.data));
            if (options.url.indexOf("?") !== -1) {
                options.url = options.url.substr(0, options.url.indexOf("?"));
            }
            xmlHttpRequest.open("GET", options.url + "?" + str, true);
            xmlHttpRequest.send(null);
        } else {
            xmlHttpRequest.open(options.type.toUpperCase(), options.url, true);
            xmlHttpRequest.setRequestHeader("Content-type", options.contentType);
            if (options.processData) {
                str = param(options.data);
            } else {
                str = options.data;
            }
            xmlHttpRequest.send(str);
        }
        xmlHttpRequest.onreadystatechange = function() {
            var textStatus = "";
            if (xmlHttpRequest.readyState === 4) {
                clearInterval(timer);
                if ((xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) || xmlHttpRequest.status === 304) {
                    if (xmlHttpRequest.status === 304) {
                        textStatus = "notmodified";
                    } else {
                        textStatus = "success";
                    }
                    try {
                        // 如果是JSON格式,自动转换为JSON对象
                        options.success(JSON.parse(xmlHttpRequest.responseText), textStatus);
                    } catch (e) {
                        options.success(xmlHttpRequest.responseText, textStatus);
                    }
                } else {
                    textStatus = "error";
                    if (typeof options.error === "function") {
                        options.error(xmlHttpRequest, textStatus);
                    }
                }
                if (typeof options.complete === "function") {
                    options.complete(xmlHttpRequest, textStatus);
                }
            }
        };
        //判断是否超时
        if (typeof options.timeout === "number") {
            timer = setTimeout(function() {
                if (typeof options.error === "function") {
                    options.error(xmlHttpRequest, "timeout");
                    options.complete(xmlHttpRequest, "timeout");
                }
                if (typeof options.complete === "function") {
                    options.complete(xmlHttpRequest, "timeout");
                }
                xmlHttpRequest.abort();
            }, options.timeout);
        }
    }

    // 合并对象
    function mergeObject(target) {
        if (target == null) {
            throw new TypeError("Cannot convert undefined or null to object");
        }
        target = Object(target);
        for (var index = 1; index < arguments.length; index++) {
            var source = arguments[index];
            if (source != null) {
                for (var key in source) {
                    if (Object.prototype.hasOwnProperty.call(source, key)) {
                        target[key] = source[key];
                    }
                }
            }
        }
        return target;
    }

    // 把url中的查询字符串转为对象,主要是想当方式为get时,用data对象的参数覆盖掉url中的参数
    function urlorQuerytoObject(urlorQuery) {
        var queryArr = [];
        var urlSplit = urlorQuery.split("?");
        queryArr[0] = urlSplit[0];
        if (urlSplit[1]) {
            queryArr[0] = urlSplit[1];
        }
        queryArr = queryArr[0].split("&");
        var obj = {};
        var i = 0;
        var temp;
        var key;
        var value;
        while (i < queryArr.length) {
            temp = queryArr[i].split("=");
            key = temp[0];
            value = temp[1];
            obj[key] = value;
            i++;
        }
        return obj;
    }

    // 序列化参数
    // 转载自 https://www.jianshu.com/p/0ca22d53feea
    function param(obj, traditional) {
        if (traditional === "undefined") {
            traditional = false;
        }
        var rbracket = /\[\]$/,
            op = Object.prototype,
            ap = Array.prototype,
            aeach = ap.forEach,
            ostring = op.toString;

        function isFunction(it) {
            return ostring.call(it) === "[object Function]";
        }

        function isArray(it) {
            return ostring.call(it) === "[object Array]";
        }

        function isObject(it) {
            return ostring.call(it) === "[object Object]";
        }

        function buildParams(prefix, obj, traditional, add) {
            var name;
            if (isArray(obj)) {
                // Serialize array item.
                aeach.call(obj, function(v, i) {
                    if (traditional || rbracket.test(prefix)) {
                        // Treat each array item as a scalar.
                        add(prefix, v);
                    } else {
                        // Item is non-scalar (array or object), encode its numeric index.
                        buildParams(
                            prefix + "[" + (typeof v === "object" && v != null ? i : "") + "]",
                            v,
                            traditional,
                            add
                        );
                    }
                });
            } else if (!traditional && isObject(obj)) {
                // Serialize object item.
                for (name in obj) {
                    buildParams(prefix + "[" + name + "]", obj[name], traditional, add);
                }
            } else {
                // Serialize scalar item.
                add(prefix, obj);
            }
        }

        // Serialize an array of form elements or a set of
        // key/values into a query string
        function jollyparam(a, traditional) {
            var prefix,
                s = [],
                add = function(key, valueOrFunction) {
                    // If value is a function, invoke it and use its return value
                    var value = isFunction(valueOrFunction) ? valueOrFunction() : valueOrFunction;
                    s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value == null ? "" : value);
                };
            // If an array was passed in, assume that it is an array of form elements.
            if (isArray(a)) {
                // Serialize the form elements
                aeach.call(a, function(item) {
                    add(item.name, item.value);
                });
            } else {
                // If traditional, encode the "old" way (the way 1.3.2 or older
                // did it), otherwise encode params recursively.
                for (prefix in a) {
                    buildParams(prefix, a[prefix], traditional, add);
                }
            }
            // Return the resulting serialization
            return s.join("&");
        }

        return jollyparam(obj, traditional);
    }

    $ = {
        get: function(url, data, success) {
            return ajax({ url: url, data: data, success: success });
        },
        post: function(url, data, success) {
            return ajax({
                type: "POST",
                url: url,
                data: data,
                success: success
            });
        },
        ajax: ajax,
        param: param,
        urlorQuerytoObject: urlorQuerytoObject,
        mergeObject: mergeObject
    };

    // 满足 JQuery 的使用习惯
    if (typeof window.$ === "undefined") {
        window.$ = $;
    }
})(Ajax);

 

用法

高度模仿JQ。

// get请求
$.get("", {}, function(data) {});

// post请求
$.post("", {}, function(data) {});

// 更完整的ajax
$.ajax({
    type: "post", // 非必须,默认 get
    url: "",
    data: {  },
    xhrFields: {
        // 非必须,自定义 XHR 对象属性
        withCredentials: true
    },
    processData: true, // 非必须,默认 true
    contentType: "application/x-www-form-urlencoded", // 非必须,默认 application/x-www-form-urlencoded
    success: function(responseData, textStatus) {
        // textStatus : "success"、"notmodified"
    },
    // timeout: 1, // 非必须,超时毫秒数,如果设置了,超时且存在error函数则会调用
    error: function(xhr, textStatus) {
        // 非必须
        // textStatus: "error"、"timeout"
    },
    complete: function(xhr, textStatus) {
        // 非必须,无论成败最后均调用
        // textStatus:  "success"、"notmodified"、"error"、"timeout"
    }
});

注意事项

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

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

 

 

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

github

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值