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" );
    }
  • 相关阅读:
    target runtime apache v6.0 not defined解决
    java.lang.AbstractMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;
    The valid characters are defined in RFC 7230 and RFC 3986问题
    invalid END header解决方法
    You have more than one version of ‘org.apache.commons.logging.Log’ visible, which is not allowed问题解决
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    在eclipse中import java web项目时遇到的一些问题并将该项目通过tomcat发布
    java byte转string 涉及到字节流中有中文
    spring+mybatis框架搭建时遇到Mapped Statements collection does not contain value for...的错误
    试试看读一下Zepto源码
  • 原文地址:https://www.cnblogs.com/justany/p/2979456.html
Copyright © 2011-2022 走看看