久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      jQuery的設(shè)計模式是什么

      jQuery中的設(shè)計模式有:1、組合模式,描述了一組對象可像單個對象一樣的對待;2、適配器模式;3、外觀模式;4、觀察者模式;5、迭代器模式;6、惰性初始模式;7、代理模式;8、建造者模式。

      jQuery的設(shè)計模式是什么

      本教程操作環(huán)境:windows7系統(tǒng)、jquery3.5版本、Dell G3電腦。

      推薦教程:jQuery教程

      jQuery中的設(shè)計模式

      jQuery是目前最流行的JavaScript DOM操作庫,它提供了一個在安全和跨瀏覽器的方式下與DOM交互的抽象層。有意思的是,這個庫也可以作為一個例子,來展示設(shè)計模式如何有效的創(chuàng)建既可讀又易用的API。

      雖然在很多情況下,撰寫jQuery的主要貢獻者并沒有打算使用特定的模式,但是這些設(shè)計模式確實存在,而且對我們學(xué)習(xí)來說,非常有用。

      組合模式

      組合模式 描述了一組對象可像單個對象一樣的對待。

      這允許我們能統(tǒng)一的處理單個對象或多個對象。這意味著無論是一個對象還是一千個對象我們都能以同樣的行為來處理。

      在Jquery中,當(dāng)我們在一個節(jié)點或多個節(jié)點上應(yīng)用方法時,我們都能以相同的方式來選擇并返回JQuery對象。

      下面這個演示我們將使用Jquery的選擇器。對單一元素(比如擁有唯一ID的元素)或擁有相同標(biāo)簽或Class的一組元素添加名為active的class,對待它們使用上并無不同:

      // 單一節(jié)點 $( "#singleItem" ).addClass( "active" ); $( "#container" ).addClass( "active" );  // 一組節(jié)點 $( "div" ).addClass( "active" ); $( ".item" ).addClass( "active" ); $( "input" ).addClass( "active" );

      JQuery的addClass()實現(xiàn)中直接使用原生的for循環(huán)、Jquery的JQuery.each()、Jquery.fn.each來迭代一個集合以達到能同時處理一個或一組元素的目的。請看下面的例子:

       addClass: function( value ) {   var classNames, i, l, elem,     setClass, c, cl;    if ( jQuery.isFunction( value ) ) {     return this.each(function( j ) {       jQuery( this ).addClass( value.call(this, j, this.className) );     });   }    if ( value && typeof value === "string" ) {     classNames = value.split( rspace );      for ( i = 0, l = this.length; i < l; i++ ) {       elem = this[ i ];        if ( elem.nodeType === 1 ) {         if ( !elem.className && classNames.length === 1 ) {           elem.className = value;          } else {           setClass = " " + elem.className + " ";            for ( c = 0, cl = classNames.length; c < cl; c++ ) {             if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {               setClass += classNames[ c ] + " ";             }           }           elem.className = jQuery.trim( setClass );         }       }     }   }    return this; }

      適配器模式

      適配器模式 將一個對象或者類的接口翻譯成某個指定的系統(tǒng)可以使用的另外一個接口。

      適配器基本上允許本來由于接口不兼容而不能一起正常工作的對象或者類能夠在一起工作.適配器將對它接口的調(diào)用翻譯成對原始接口的調(diào)用,而實現(xiàn)這樣功能的代碼通常是最簡的。

      我們可能已經(jīng)用過的一個適配器的例子就是jQuery的jQuery.fn.css()方法,這個方法幫助規(guī)范了不同瀏覽器之間樣式的應(yīng)用方式,使我們使用簡單的語法,這些語法被適配成為瀏覽器背后真正支持的語法:

      // Cross browser opacity: // opacity: 0.9;  Chrome 4+, FF2+, Saf3.1+, Opera 9+, IE9, iOS 3.2+, Android 2.1+ // filter: alpha(opacity=90);  IE6-IE8  // Setting opacity $( ".container" ).css( { opacity: .5 } );  // Getting opacity var currentOpacity = $( ".container" ).css('opacity');

      將上面的代碼變得可行的相應(yīng)的jQuery核心css鉤子在下面:

      get: function( elem, computed ) {  // IE uses filters for opacity  return ropacity.test( (        computed && elem.currentStyle ?            elem.currentStyle.filter : elem.style.filter) || "" ) ?    ( parseFloat( RegExp.$1 ) / 100 ) + "" :    computed ? "1" : ""; },  set: function( elem, value ) {  var style = elem.style,    currentStyle = elem.currentStyle,    opacity = jQuery.isNumeric( value ) ?          "alpha(opacity=" + value * 100 + ")" : "",    filter = currentStyle && currentStyle.filter || style.filter || "";   // IE has trouble with opacity if it does not have layout  // Force it by setting the zoom level  style.zoom = 1;   // if setting opacity to 1, and no other filters  //exist - attempt to remove filter attribute #6652  if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {     // Setting style.filter to null, "" & " " still leave    // "filter:" in the cssText if "filter:" is present at all,    // clearType is disabled, we want to avoid this style.removeAttribute    // is IE Only, but so apparently is this code path...    style.removeAttribute( "filter" );     // if there there is no filter style applied in a css rule, we are done    if ( currentStyle && !currentStyle.filter ) {      return;    }  }   // otherwise, set new filter values  style.filter = ralpha.test( filter ) ?    filter.replace( ralpha, opacity ) :    filter + " " + opacity; } };

      外觀模式

      正如我們早前在書中提過的, 沒面模式為一個龐大的(可能更復(fù)雜的)代碼結(jié)構(gòu)提供了一個更簡單的抽象接口。

      門面在jQuery庫中能夠經(jīng)常見到,它們?yōu)殚_發(fā)者處理DOM節(jié)點,動畫或者令人特別感興趣的跨域Ajax提供了簡單的實現(xiàn)入口。

      下面的代碼是jQuery $.ajax()方法的門面:

      $.get( url, data, callback, dataType ); $.post( url, data, callback, dataType ); $.getJSON( url, data, callback ); $.getScript( url, callback );

      這些方法背后真正執(zhí)行的代碼是這樣的:

      // $.get() $.ajax({   url: url,   data: data,   dataType: dataType }).done( callback );  // $.post $.ajax({   type: "POST",   url: url,   data: data,   dataType: dataType }).done( callback );  // $.getJSON() $.ajax({   url: url,   dataType: "json",   data: data, }).done( callback );  // $.getScript() $.ajax({   url: url,   dataType: "script", }).done( callback );

      更有趣的是,上面代碼中的門面實際上是它們自身具有的能力,它們隱藏了代碼背后很多復(fù)雜的操作。

      這是因為jQuery.ajax()在jQuery核心代碼中的實現(xiàn)是一段不平凡的代碼,至少是這樣的。至少它規(guī)范了XHR(XMLHttpRequest)之間的差異而且讓我們能夠簡單的執(zhí)行常見的HTTP動作(比如:get、post等),以及處理延遲等等。

      由于顯示與上面所講的門面相關(guān)的代碼將會占據(jù)整個章節(jié),這里僅僅給出了jQuery核心代碼中規(guī)劃化XHR的代碼:

      // Functions to create xhrs function createStandardXHR() {   try {     return new window.XMLHttpRequest();   } catch( e ) {} }  function createActiveXHR() {   try {     return new window.ActiveXObject( "Microsoft.XMLHTTP" );   } catch( e ) {} }  // Create the request object jQuery.ajaxSettings.xhr = window.ActiveXObject ?   /* Microsoft failed to properly    * implement the XMLHttpRequest in IE7 (can't request local files),    * so we use the ActiveXObject when it is available    * Additionally XMLHttpRequest can be disabled in IE7/IE8 so    * we need a fallback.    */   function() {     return !this.isLocal && createStandardXHR() || createActiveXHR();   } :   // For all other browsers, use the standard XMLHttpRequest object   createStandardXHR;   ...

      下面的代碼也處于實際的jQuery XHR(jqXHR)實現(xiàn)的上層,它是我們實際上經(jīng)常打交道的方便的門面:

      // Request the remote document    jQuery.ajax({      url: url,      type: type,      dataType: "html",      data: params,      // Complete callback (responseText is used internally)      complete: function( jqXHR, status, responseText ) {        // Store the response as specified by the jqXHR object        responseText = jqXHR.responseText;        // If successful, inject the HTML into all the matched elements        if ( jqXHR.isResolved() ) {          // Get the actual response in case          // a dataFilter is present in ajaxSettings          jqXHR.done(function( r ) {            responseText = r;          });          // See if a selector was specified          self.html( selector ?            // Create a dummy div to hold the results            jQuery("  <div>     ")              // inject the contents of the document in, removing the scripts              // to avoid any 'Permission Denied' errors in IE              .append(responseText.replace(rscript, ""))               // Locate the specified elements              .find(selector) :             // If not, just inject the full result            responseText );        }         if ( callback ) {          self.each( callback, [ responseText, status, jqXHR ] );        }      }    });     return this;  }  </div>

      觀察者模式

      另一個我們之前提到過的模式就是觀察者(發(fā)布/訂閱)模式.這種模式下,系統(tǒng)中的對象可以在關(guān)注的事件發(fā)生的時候給其他對象發(fā)送消息,也可以被其他對象所通知。

      jQuery核心庫很多年前就已經(jīng)提供了對于類似于發(fā)布/訂閱系統(tǒng)的支持,它們稱之為定制事件。

      jQuery的早期版本中,可以通過使用jQuery.bind()(訂閱),jQuery.trigger()(發(fā)布),和jQuery.unbind()(取消訂閱)來使用這些定制事件,但在近期的版本中,這些都可以通過使用jQuery.on(),jQuery.trigger()和jQuery.off()來完成。

      下面我們來看一下實際應(yīng)用中的一個例子:

      // Equivalent to subscribe(topicName, callback) $( document ).on( "topicName" , function () {     //..perform some behaviour });  // Equivalent to publish(topicName) $( document ).trigger( "topicName" );  // Equivalent to unsubscribe(topicName) $( document ).off( "topicName" );

      對于jQuery.on()和jQuery.off()的調(diào)用最后會經(jīng)過jQuery的事件系統(tǒng),與Ajax一樣,由于它們的實現(xiàn)代碼相對較長,我們只看一下實際上事件處理器是在哪兒以及如何將定制事件加入到系統(tǒng)中的:

      jQuery.event = {    add: function( elem, types, handler, data, selector ) {      var elemData, eventHandle, events,       t, tns, type, namespaces, handleObj,       handleObjIn, quick, handlers, special;      ...      // Init the element's event structure and main handler,     //if this is the first     events = elemData.events;     if ( !events ) {       elemData.events = events = {};     }     ...      // Handle multiple events separated by a space     // jQuery(...).bind("mouseover mouseout", fn);     types = jQuery.trim( hoverHack(types) ).split( " " );     for ( t = 0; t < types.length; t++ ) {        ...        // Init the event handler queue if we're the first       handlers = events[ type ];       if ( !handlers ) {         handlers = events[ type ] = [];         handlers.delegateCount = 0;          // Only use addEventListener/attachEvent if the special         // events handler returns false         if ( !special.setup || special.setup.call( elem, data,         //namespaces, eventHandle ) === false ) {           // Bind the global event handler to the element           if ( elem.addEventListener ) {             elem.addEventListener( type, eventHandle, false );            } else if ( elem.attachEvent ) {             elem.attachEvent( "on" + type, eventHandle );           }         }       }

      對于那些喜歡使用傳統(tǒng)的命名方案的人, Ben Alamn對于上面的方法提供了一個簡單的包裝,然后為我們提供了jQuery.publish(),jQuery.subscribe和jQuery.unscribe方法。我之前在書中提到過,現(xiàn)在我們可以完整的看一下這個包裝器。

      (function( $ ) {    var o = $({});    $.subscribe = function() {     o.on.apply(o, arguments);   };    $.unsubscribe = function() {     o.off.apply(o, arguments);   };    $.publish = function() {     o.trigger.apply(o, arguments);   };  }( jQuery ));

      在近期的jQuery版本中,一個多目的的回調(diào)對象(jQuery.Callbacks)被提供用來讓用戶在回調(diào)列表的基礎(chǔ)上寫新的方案。另一個發(fā)布/訂閱系統(tǒng)就是一個使用這個特性寫的方案,它的實現(xiàn)方式如下:

      var topics = {};  jQuery.Topic = function( id ) {     var callbacks,         topic = id && topics[ id ];     if ( !topic ) {         callbacks = jQuery.Callbacks();         topic = {             publish: callbacks.fire,             subscribe: callbacks.add,             unsubscribe: callbacks.remove         };         if ( id ) {             topics[ id ] = topic;         }     }     return topic; };

      然后可以像下面一樣使用:

      // Subscribers $.Topic( "mailArrived" ).subscribe( fn1 ); $.Topic( "mailArrived" ).subscribe( fn2 ); $.Topic( "mailSent" ).subscribe( fn1 );  // Publisher $.Topic( "mailArrived" ).publish( "hello world!" ); $.Topic( "mailSent" ).publish( "woo! mail!" );  //  Here, "hello world!" gets pushed to fn1 and fn2 //  when the "mailArrived" notification is published //  with "woo! mail!" also being pushed to fn1 when //  the "mailSent" notification is published.  // Outputs: // hello world! // fn2 says: hello world! // woo! mail!

      迭代器模式

      迭代器模式中,迭代器(允許我們遍歷集合中所有元素的對象)順序迭代一個集合對象中的元素而無需暴漏其底層形式。

      迭代器封裝了這種特別的迭代操作的內(nèi)部結(jié)構(gòu),就jQuery的jQuery.fn.each()迭代器來說,我們實際上可以使用jQuery.each()底層的代碼來迭代一個集合,而無需知道或者理解后臺提供這種功能的代碼是如何實現(xiàn)的。

      這種模式可以被理解為門面模式的一種特例,在這里我們只處理與迭代有關(guān)的問題。

      $.each( ["john","dave","rick","julian"] , function( index, value ) {   console.log( index + ": "" + value); });  $( "li" ).each( function ( index ) {   console.log( index + ": " + $( this ).text()); });

      這里我們可以看到j(luò)Query.fn.each()的代碼:

      // Execute a callback for every element in the matched set. each: function( callback, args ) {   return jQuery.each( this, callback, args ); }

      在jQuery.each()方法后面的代碼提供了兩種迭代對象的方法:

      each: function( object, callback, args ) {   var name, i = 0,     length = object.length,     isObj = length === undefined || jQuery.isFunction( object );    if ( args ) {     if ( isObj ) {       for ( name in object ) {         if ( callback.apply( object[ name ], args ) === false ) {           break;         }       }     } else {       for ( ; i < length; ) {         if ( callback.apply( object[ i++ ], args ) === false ) {           break;         }       }     }    // A special, fast, case for the most common use of each   } else {     if ( isObj ) {       for ( name in object ) {         if ( callback.call( object[ name ], name, object[ name ] ) === false ) {           break;         }       }     } else {       for ( ; i < length; ) {         if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {           break;         }       }     }   }    return object; };

      惰性初始模式

      延遲初始化 是一種允許我們延遲初始化消耗資源比較大的進程,直到需要他們的時候(才初始化)。這其中的一個例子就是jQuery的.ready()方法,它在DOM節(jié)點加載完畢之后會執(zhí)行一個回調(diào)方法。

      $( document ).ready( function () {      //ajax請求不會執(zhí)行,直到DOM加載完成      var jqxhr = $.ajax({       url: "http://domain.com/api/",       data: "display=latest&order=ascending"     })     .done( function( data ) ){         $(".status").html( "content loaded" );         console.log( "Data output:" + data );     });  });

      jQuery.fn.ready()底層是通過byjQuery.bindReady()來實現(xiàn)的, 如下所示:

      bindReady: function() {   if ( readyList ) {     return;   }    readyList = jQuery.Callbacks( "once memory" );    // Catch cases where $(document).ready() is called after the   // browser event has already occurred.   if ( document.readyState === "complete" ) {     // Handle it asynchronously to allow scripts the opportunity to delay ready     return setTimeout( jQuery.ready, 1 );   }    // Mozilla, Opera and webkit support this event   if ( document.addEventListener ) {     // Use the handy event callback     document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );      // A fallback to window.onload, that will always work     window.addEventListener( "load", jQuery.ready, false );    // If IE event model is used   } else if ( document.attachEvent ) {     // ensure firing before onload,     // maybe late but safe also for iframes     document.attachEvent( "onreadystatechange", DOMContentLoaded );      // A fallback to window.onload, that will always work     window.attachEvent( "onload", jQuery.ready );      // If IE and not a frame     // continually check to see if the document is ready     var toplevel = false;      try {       toplevel = window.frameElement == null;     } catch(e) {}      if ( document.documentElement.doScroll && toplevel ) {       doScrollCheck();     }   } },

      即使不直接在jQuery核心文件中使用,有些開發(fā)者通過一些插件也可能熟悉懶加載的概念,延遲加載和攬初始化一樣有效,它是一種在需要的時候(比如:當(dāng)用戶瀏覽到了頁面底部的時候)才加載頁面數(shù)據(jù)的技術(shù)。最近幾年,這種模式已經(jīng)變得非常顯著并且現(xiàn)在可以再Twitter和Facebook的UI里面zhaoda。

      代理模式

      在我們需要在一個對象后多次進行訪問控制訪問和上下文,代理模式是非常有用處的。

      當(dāng)實例化一個對象開銷很大的時候,它可以幫助我們控制成本,提供更高級的方式去關(guān)聯(lián)和修改對象,就是在上下文中運行一個特別的方法。

      在jQuery核心中,一個jQUery.proxy()方法在接受一個函數(shù)的輸入和返回一個一直具有特殊上下文的新的實體時存在。這確保了它在函數(shù)中的值時我們所期待的的值。

      一個使用該模式的例子,在點擊事件操作時我們利用了定時器。設(shè)想我用下面的操作優(yōu)先于任何添加的定時器:

      $( "button" ).on( "click", function () {   // 在這個函數(shù)中,'this'代表了被當(dāng)前被點擊的那個元素對象   $( this ).addClass( "active" ); });

      如果想要在addClass操作之前添加一個延遲,我們可以使用setTiemeout()做到。然而不幸的是這么操作時會有一個小問題:無論這個函數(shù)執(zhí)行了什么在setTimeout()中都會有個一個不同的值在那個函數(shù)中。而這個值將會關(guān)聯(lián)window對象替代我們所期望的被觸發(fā)的對象。

      $( "button" ).on( "click", function () {   setTimeout(function () {     // "this" 無法關(guān)聯(lián)到我們點擊的元素     // 而是關(guān)聯(lián)了window對象     $( this ).addClass( "active" );   }); });

      為解決這類問題,我們使用jQuery.proxy()方法來實現(xiàn)一種代理模式。通過調(diào)用它在這個函數(shù)中,使用這個函數(shù)和我們想要分配給它的this,我們將會得到一個包含了我們所期望的上下文中的值。如下所示:

      $( "button" ).on( "click", function () {      setTimeout( $.proxy( function () {         // "this" 現(xiàn)在關(guān)聯(lián)了我們想要的元素         $( this ).addClass( "active" );      }, this), 500);      // 最后的參數(shù)'this'代表了我們的dom元素并且傳遞給了$.proxy()方法 });

      jQuery代理方法的實現(xiàn)如下:

      // Bind a function to a context, optionally partially applying any  // arguments.  proxy: function( fn, context ) {    if ( typeof context === "string" ) {      var tmp = fn[ context ];      context = fn;      fn = tmp;    }     // Quick check to determine if target is callable, in the spec    // this throws a TypeError, but we will just return undefined.    if ( !jQuery.isFunction( fn ) ) {      return undefined;    }     // Simulated bind    var args = slice.call( arguments, 2 ),      proxy = function() {        return fn.apply( context, args.concat( slice.call( arguments ) ) );      };     // Set the guid of unique handler to the same of original handler, so it can be removed    proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;     return proxy;  }

      建造者模式

      處理DOM時,我們常常想要去動態(tài)的構(gòu)建新的元素–這是一個會讓我們希望構(gòu)建的元素最終所包含的標(biāo)簽,屬性和參數(shù)的復(fù)雜性有所增長的過程。

      定義復(fù)雜的元素時需要特別的小心,特別是如果我們想要在我們元素標(biāo)簽的字面意義上(這可能會亂成一團)擁有足夠的靈活性,或者取而代之去獲得

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號