zoukankan      html  css  js  c++  java
  • jQuery ajax —— 一些细节以及主函数扩展出来的方法

    上一篇文章,讲解了jQuery.ajax函数。这篇文章将其他一些细节补充完。下一篇文章则开始讲解,jQuery是如何将script动态载入、XMLHttpRequest、JSONP一起包装进jQuery.ajax里的。

    jQuery.ajaxSetup

    我们可以从主函数看出,参数是通过jQuery.ajaxSetup产生的:

    // 通过jQuery.ajaxSetup改造参数对象
    s = jQuery.ajaxSetup( {}, options ),

    那么jQuery.ajaxSetup在干些什么呢?

    jQuery.ajaxSetup = function( target, settings ) {
        // 如果有参数
        return settings ?
    
            // 创建一个设置对象,先将jQuery.ajaxSettings的属性放进去,
            // 然后将参数也放进去
            ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
    
            // 并将设置对象的属性放进jQuery.ajaxSettings对象里
            ajaxExtend( jQuery.ajaxSettings, target );
    };

    ajaxExtend

    ajaxExtend和jQuery.extend有一些不同,避免有些不需要深复制的属性进行深复制。

    function ajaxExtend( target, src ) {
        var key, deep,
            flatOptions = jQuery.ajaxSettings.flatOptions || {};
        
        // 遍历src对象中的所有key
        for ( key in src ) {
            // 如果值不是undefined
            if ( src[ key ] !== undefined ) {
                // 判断是不是不需要深复制的,如果不需要深复制,将属性直接写进target,
                // 否则写进deep里存起来
                // 我们可以从jQuery.ajaxSettings.flatOptions看到,
                // 实际上不需要深复制的是url和context
                ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
            }
        }
        
        // 如果deep不是undefined,证明需要深复制
        if ( deep ) {
            // 开始深复制
            jQuery.extend( true, target, deep );
        }
    
        // 返回target
        return target;
    }

    ajaxHandleResponses

    主体函数中response是通过ajaxHandleResponses来处理的:

    // 得到响应数据
    if ( responses ) {
        // 通过ajaxHandleResponses处理数据
        response = ajaxHandleResponses( s, jqXHR, responses );
    }

    我们来看看该函数干了些什么。

    function ajaxHandleResponses( s, jqXHR, responses ) {
    
        var ct, type, finalDataType, firstDataType,
            contents = s.contents,
            dataTypes = s.dataTypes,
            responseFields = s.responseFields;
    
        // 将responseXXX填入jqXHR指定位置,也就是responseXML或者responseText
        // 其中jqXHR.xml对应responseXML,jqXHR.text对应responseText
        for ( type in responseFields ) {
            if ( type in responses ) {
                jqXHR[ responseFields[type] ] = responses[ type ];
            }
        }
    
        // 删除掉通配dataType,得到返回的Content-Type
        while( dataTypes[ 0 ] === "*" ) {
            dataTypes.shift();
            if ( ct === undefined ) {
                ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
            }
        }
    
        // 看看是不是我们能处理的Content-Type,比如图片这类二进制类型就不好处理了
        if ( ct ) {
            // 实际上能处理的就是text、xml和json
            for ( type in contents ) {
                if ( contents[ type ] && contents[ type ].test( ct ) ) {
                    // 如果是这三种类型,则推入dataTypes里
                    dataTypes.unshift( type );
                    break;
                }
            }
        }
    
        // 如果dataTypes是我们想要的,也就是text、xml、json
        if ( dataTypes[ 0 ] in responses ) {
            // 则最终dataType就是这个了
            finalDataType = dataTypes[ 0 ];
        // 否则
        } else {
            // 尝试转换成我们要的dataType
            for ( type in responses ) {
                // 如果dataTypes[ 0 ]不存在,则直接用type作为最终dataType
                // 否则,看看能不能转换,能的话就用type作为最终dataType
                if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
                    finalDataType = type;
                    break;
                }
                // 保存第一个type
                if ( !firstDataType ) {
                    firstDataType = type;
                }
            }
            // 用最终dataType或者用第一个type
            finalDataType = finalDataType || firstDataType;
        }
    
        // 如果有最终dataType
        if ( finalDataType ) {
            // 如果最终dataType不是dataTypes[ 0 ]
            if ( finalDataType !== dataTypes[ 0 ] ) {
                // 将finalDataType推入dataTypes队列里
                dataTypes.unshift( finalDataType );
            }
            // 返回responses对应的finalDataType数据
            return responses[ finalDataType ];
        }
    }

    jQuery.fn.load

    实际上有两个jQuery.fn.load,一个是类似于onload的方法,另一个则是载入指定html页面。

    前一个是jQuery.fn.on的简单扩展,而后面一个则是使用jQuery.ajax方法的扩展。

    jQuery.fn.load = function( url, params, callback ) {
        // 如果url不是string,且_load存在
        // 证明这是onload方法,则调用保存的_load方法
        if ( typeof url !== "string" && _load ) {
            return _load.apply( this, arguments );
        }
    
        var selector, type, response,
            self = this,
            off = url.indexOf(" ");
    
        // 看看是不是载入指定元素,比如参数是'ajax/test.html #container'
        if ( off >= 0 ) {
            // 分隔出需要载入的元素
            selector = url.slice( off, url.length );
            // 分隔出真正的url
            url = url.slice( 0, off );
        }
    
        // 模拟重载
        if ( jQuery.isFunction( params ) ) {
    
            // 如果是函数那么就当这个是回调函数
            callback = params;
            params = undefined;
    
        // 如果参数是objects,那么定义type是POST
        } else if ( params && typeof params === "object" ) {
            type = "POST";
        }
    
        // 如果有需要修改的元素,开始请求
        if ( self.length > 0 ) {
            jQuery.ajax({
                url: url,
    
                // 如果type为undefined,那么就会缺省为GET方法
                type: type,
                dataType: "html",
                data: params
                // 完成后回调
            }).done(function( responseText ) {
    
                // 保存reponse
                response = arguments;
    
                // 对元素写入html
                // 如果selector存在
                self.html( selector ?
    
                    // 先用一个div来存储整个html页面的DOM,在找到selector的相关html
                    jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
    
                    // 否则直接用responseText
                    responseText );
    
                // 如果回调函数存在,则回调
            }).complete( callback && function( jqXHR, status ) {
                self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
            });
        }
    
        return this;
    };

    jQuery.get & jQuery.post

    这两个方法实际上就是通过jQuery.ajax扩展而来的。

    // 加上get和post方法
    jQuery.each( [ "get", "post" ], function( i, method ) {
        // jQuery.get或jQuery.post为
        jQuery[ method ] = function( url, data, callback, type ) {
            // 模拟重载
            if ( jQuery.isFunction( data ) ) {
                type = type || callback;
                callback = data;
                data = undefined;
            }
    
            // 利用jQuery.ajax完成任务
            return jQuery.ajax({
                url: url,
                type: method,
                dataType: type,
                data: data,
                success: callback
            });
        };
    });

    jQuery.getScript & jQuery.getJSON

    jQuery.getScript和jQuery.getJSON则是由jQuery.get扩展而来的。

    jQuery.getScript = function( url, callback ) {
        return jQuery.get( url, undefined, callback, "script" );
    };
    jQuery.getJSON = function( url, data, callback ) {
        return jQuery.get( url, data, callback, "json" );
    }
  • 相关阅读:
    [BZOJ]1042 硬币购物(HAOI2008)
    [Codeforces]605E Intergalaxy Trips
    [Codeforces]860E Arkady and a Nobody-men
    [Codeforces]856E Satellites
    [Codeforces]849E Goodbye Souvenir
    [Codeforces]852I Dating
    [BZOJ]1095 Hide捉迷藏(ZJOI2007)
    洛谷3275 & BZOJ2330:[SCOI2011]糖果——题解
    洛谷5960:【模板】差分约束算法——题解
    The Preliminary Contest for ICPC Asia Nanjing 2019/2019南京网络赛——题解
  • 原文地址:https://www.cnblogs.com/justany/p/2979456.html
Copyright © 2011-2022 走看看