首頁  >  文章  >  web前端  >  jQuery1.9.1源碼分析系列(十六)ajax之ajax框架_jquery

jQuery1.9.1源碼分析系列(十六)ajax之ajax框架_jquery

WBOY
WBOY原創
2016-05-16 15:27:31923瀏覽

AJAX 簡介

AJAX 是一種在無需重新載入整個網頁的情況下,能夠更新部分網頁的技術。

您應具備的基礎知識

在繼續學習之前,您需要對以下的知識有基本的了解:

HTML / XHTML
CSS
JavaScript / DOM

如果您希望先學習這些項目,請在我們的首頁造訪這些教學。

什麼是 AJAX ?

AJAX = 非同步 JavaScript 和 XML。

AJAX 是一種用於建立快速動態網頁的技術。

透過在後台與伺服器進行少量資料交換,AJAX 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某個部分進行更新。

傳統的網頁(不使用 AJAX)如果需要更新內容,則必須重載整個網站頁面。

有許多使用 AJAX 的應用程式案例:新浪微博、Google 地圖、開心網等等。

Google Suggest

在 2005 年,Google 透過其 Google Suggest 讓 AJAX 變得流行起來。

Google Suggest 使用 AJAX 創造出動態性極強的 web 介面:當您在Google的搜尋方塊輸入關鍵字時,JavaScript 會將這些字元傳送到伺服器,然後伺服器會傳回搜尋建議的清單。

今天就開始使用 AJAX

AJAX 是基於現有的標準。這些標準已被大多數開發者使用多年。

既然是ajax框架,那麼閒聊一談jQuery的ajax處理思路。

  現在的瀏覽器都支援ajax,只不過不同的瀏覽器使用方法可能有不同(IE使用new window.ActiveXObject("Microsoft.XMLHTTP"),標準瀏覽器使用new window.XMLHttpRequest())。如果照著這種思路,貌似jQajax只需要做好相容處理就行了?

  不是的,原生的ajax有一個說大不大說小不小的缺點-不支持跨域(同源策略由來已久,自行百度)。所以jQajax加入了這方面的處理,jQajax是如何解決跨域問題的?

  jQuery1.9.1源碼分析系列(十六)ajax之ajax框架_jqueryhttp://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, "\r\n" ) };
    }) :
    { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  }).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;
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn