zoukankan      html  css  js  c++  java
  • jQuery-1.9.1源码分析系列(十六)ajax——ajax框架

      ajax的介绍就不多说了,点击可看.

      既然是ajax框架,那么闲谈一谈jQuery的ajax处理思路。

      现在的浏览器都支持ajax,只不过不同的浏览器使用方法可能有不同(IE使用new window.ActiveXObject("Microsoft.XMLHTTP"),标准浏览器使用new window.XMLHttpRequest())。如果按照这种思路,貌似jQajax只需要做好兼容处理就行了?

      不是的,原生的ajax有一个说大不大说小不小的缺点——不支持跨域(同源策略由来已久,自行百度)。所以jQajax添加了这方面的处理,jQajax是如何解决跨域问题的?

      <img src="http://img2.imgtn.bdimg.com/it/u=2406301718,2822592556&fm=21&gp=0.jpg"/>

      是能取到图片的,很明显图片的路径和你的服务端不是一个域的。你可以试试看所有的带有src属性的标签都不受同源策略的影响。所以,jQuery就使用了这个属性,对于跨域请求使用script标签的src来请求路径

      然后jQuery在加上对ajax事件的三种监听方式:

      1.全局事件:$(document).on(‘ajaxStart’,func);

      2.ajax设置回调项:$.ajax({url: "php.html", complete: func });

      3.deferred绑定方式:$.ajax(…).done(func);

      基本上这就是jQajax所做的事情。

      在正真进入ajax框架核心之前,先来分析一jQuery准备的几个序列化提交表单的函数。

    a. 表单序列化


      所谓的表单序列化即将表单需要提交的内容组成类似:“key=value&key=value…”形式的字符串。

      序列化用到三个函数:

      jQuery.fn. serialize()(序列化函数,筛选出表单中需要提交的数据并以序列化字符串方式返回,形如:“key=value&key=value…”)

      jQuery.fn. serializeArray()(筛选出表单中需要提交的数据并以key/value键值对的对象数组格式返回,返回[{name:’key’,value:’select1’},{name:’selectM’,value:’selectM1’}, {name:’selectM’,value:’selectM2’}, { name:’key2’,value:0}…])

      jQuery.param(serializeArray, traditional )(将key/value键值对的对象数组序列化为“key=value&key=value…”字符串)。

      

      serialize直接调用jQuery.param( this.serializeArray() )即可。

      serializeArray的源码如下主要进行三个步骤:提取表单元素、过滤出满足提交条件的表单元素、组合成key/value键值对的对象数组

    serializeArray: function() {
        //将form中的表单相关的元素取出来组成数组
        return this.map(function(){
            //表单节点有elements这个特征
            var elements = jQuery.prop( this, "elements" );
            return elements ? jQuery.makeArray( elements ) : this;
        })
        //过滤出为需要提交的表单元素(有name名称、非disabled元素、非提交按钮等元素、checkbox/radio的checked的元素)
        .filter(function(){
            var type = this.type;
            //使用.is(":disabled")过滤掉不可用的表单元素
            return this.name && !jQuery( this ).is( ":disabled" ) &&
            rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
            ( this.checked || !manipulation_rcheckableType.test( type ) );
        })
        //将表单提交元素组成name和value的对象数组
        .map(function( i, elem ){
            var val = jQuery( this ).val();
    
            return val == null ?
            null :
            jQuery.isArray( val ) ?
            jQuery.map( val, function( val ){
                return { name: elem.name, value: val.replace( rCRLF, "
    " ) };
            }) :
            { name: elem.name, value: val.replace( rCRLF, "
    " ) };
        }).get();
    }

      需要注意的是jQuery的过滤结果符合正常的表单提交结果://过滤出为需要提交的表单元素(有name名称、非disabled元素、非提交按钮等元素、checkbox/radio的checked的元素)

      param函数源码如下:主要进行两个处理:将key/value成作为URI组件编码(保证key和value不会出现特殊符号,即保证了“=”分割的正确性)、使用“&”链接并将空白符被替换成了"+"

    jQuery.param = function( a, traditional ) {
        var prefix,
        s = [],
        add = function( key, value ) {
                //如果value是函数,执行他得到真正的value
                value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
                //把key和value作为URI组件编码,保证key和value不会出现特殊符号,即保证了“=”分割的正确性
                s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
            };
    
        ...
    
        //传入的是数组,假设他是一个form表单键值对数组
        if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
            //序列化表单元素
            jQuery.each( a, function() {
                add( this.name, this.value );
            });
    
        } else {
            ...
        }
    
        //返回序列化结果,注意:空白符被替换成了"+"
        return s.join( "&" ).replace( r20, "+" );
    };

      其中encodeURIComponent详细点击查看

    b. ajax的事件监听


      给ajax绑定事件有三种方式

      1.全局事件:$(document).on(‘ajaxStart’,func);

      2.ajax设置回调项:$.ajax({url: "php.html", complete: func });

      3.deferred绑定方式:$.ajax(…).done(func);

      接下来我们一一讲解他们的实现。

    全局事件(ajaxStart/ajaxStop/ajaxComplete/ajaxError/ajaxSuccess/ajaxSend)

      使用.on事件绑定这种通用方式我们毫无疑问是可以绑定ajax监听事件,除此之外还可以直接使用$(…).ajaxStart(func)来绑定事件。他们的实现也是用.on来绑定。

    jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
            jQuery.fn[ type ] = function( fn ){
                return this.on( type, fn );
            };
    });

      触发事件比较简单,在进行ajax处理过程中在合适的时机直接使用jQuery.event.trigger直接触发。以ajaxStart为例

                //如果此时没有正在执行的请求,则触发ajaxStart事件
                if ( fireGlobals && jQuery.active++ === 0 ) {
                    jQuery.event.trigger("ajaxStart");
                }

      

    ajax设置回调项(beforeSend/complete/success/error)

      触发设置回调项分两种:beforeSend直接在适当的时机调用。源码

    //调用beforeSend回调,如果回调返回失败或abort则返回中止
    if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
                    //中止如果没有准备好
                    return jqXHR.abort();
                }

      complete/success/error则利用Deferred的特性将回调添加到延时队列,等待延时状态处理。源码

    //创建最终选项对象
    s = jQuery.ajaxSetup( {}, options )
    ...
    deferred = jQuery.Deferred(),
    completeDeferred = jQuery.Callbacks("once memory"),
    ...
    
    //添加延时事件
    deferred.promise( jqXHR ).complete = completeDeferred.add;
    jqXHR.success = jqXHR.done;
    jqXHR.error = jqXHR.fail;
    
    //安装回调到deferreds上
    for ( i in { success: 1, error: 1, complete: 1 } ) {
    jqXHR[ i ]( s[ i ] );
    }
    
    //在ajax请求完成的处理函数中执行completeDeferred的延时列表
    function done(){
    ...
    //执行Complete处理
    completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
    ...
    }

    deferred方式绑定回调

      Deferred方式绑定事件就不用特别说明了,因为ajax本身就是一个延时对象。直接使用$.ajax(…).done(fn).fail(fn). progress(fn).always(fn).then(fn)。源码

    deferred = jQuery.Deferred(),
    completeDeferred = jQuery.Callbacks("once memory"),
    ...
    deferred.promise( jqXHR ).complete = completeDeferred.add;
    ...
    return jqXHR;
  • 相关阅读:
    django项目一:基于django2.2可重用登录与注册模块-图片验证码
    django项目一:基于django2.2可重用登录与注册模块-Django表单
    django项目一:基于django2.2可重用登录与注册模块-登录视图函数
    谈谈我的移动端rem适配方案
    微信公众号jssdk自定义分享,二次分享自定义失败解决技巧
    html-webpack-plugin的使用
    formData 无需form异步上传多个图片
    原生javascript跨浏览器常用事件处理
    apache+php+mysql运行环境
    MySQL企业级备份
  • 原文地址:https://www.cnblogs.com/chuaWeb/p/jQuery-1-9-1-ajax-1.html
Copyright © 2011-2022 走看看