jQuery鏈式調用與show知識淺析,jquery鏈式

來源:互聯網
上載者:User

jQuery鏈式調用與show知識淺析,jquery鏈式

上篇文章給大家介紹了jQuery的架構,有關jquery的基礎知識可以參考下。

jQuery使用許久了,但是有一些API的實現實在想不通。下面將使用簡化的代碼來介紹,主要關注jQuery的實現思想。

相較於上一篇,代碼更新了:21~78

(function(window, undefined){function jQuery(sel){return new jQuery.prototype.init(sel);}jQuery.prototype = {constructor: jQuery,init: function(sel){if(typeof sel === 'string'){var that = this;var nodeList = document.querySelectorAll(sel);Array.prototype.forEach.call(nodeList, function(val, i){that[i] = val;})this.selector = sel;this.length = nodeList.length;}},show: function(){Array.prototype.forEach.call(this, function(node){//if(node.style) continue; //textnode沒有style//刪除style上的display:nonevar display = node.style.display;if(display === 'none'){//dispaly置為空白後,css如果有display則css的生效//否則預設的生效node.style.display = '';}//元素display值為非預設值情況,需要還原為oldDisplay:div->display:inline-block//或 檢測css上的display是否為noneif(node.style.display==='' || isHidden(node)){//有oldDispaly則設定if(node.oldDisplay) node.style.display = node.oldDisplay;//沒有則設定為元素預設值或元素當前值else node.style.display = getDisplay(node);}})//鏈式調用return this;},hide: function(){Array.prototype.forEach.call(this, function(node){if(!isHidden(node)) {//jQuery使用其cache機制儲存資訊,這裡簡化一下//直接掛載在對應的dom下node.oldDisplay = getDisplay(node);node.style.display = 'none';}})return this;}}function getDisplay(node){var display = window.getComputedStyle(node, null).getPropertyValue('display');if(display === 'none'){var dom = document.createElement(node.nodeName);//插入到body中document.body.appendChild(dom);//即可擷取到元素display的預設值var display = window.getComputedStyle(dom, null).getPropertyValue('display');document.body.removeChild(dom);}return display;}function isHidden(node) {//忽略未append進document的元素這種隱藏情況:$('<div>block</div>')未appendreturn window.getComputedStyle(node, null).getPropertyValue('display') === 'none';}jQuery.prototype.init.prototype = jQuery.prototype;window.$ = jQuery;})(window); 

先拿hide函數熱身一下。如上篇提到的,jQuery會將擷取到的nodeList處理成數組,所以一上來,我們用forEach處理數組裡的每一個node節點。

接下來,我們只需要將每一個節點的style.display置為'none'即可隱藏。很簡單,對吧?(⊙0⊙) 。oldDisplay和return this先不管╰( ̄▽ ̄)╮

hide: function(){Array.prototype.forEach.call(this, function(node){if(!isHidden(node)) {//jQuery使用其cache機制儲存資訊,這裡簡化一下//直接掛載在對應的dom下node.oldDisplay = getDisplay(node);node.style.display = 'none';}})return this;} 

其中isHidden是判斷該元素是否隱藏:已經隱藏的元素就沒必要再去處理了,直接跳過

function isHidden(node) {//忽略未append進document的元素這種隱藏情況:$('<div>block</div>')未appendreturn window.getComputedStyle(node, null).getPropertyValue('display') === 'none';}

--------------------------

接下來,來個稍繁瑣的show。先拋出一個問題來引發一系列問題:

hide某個元素只需要將display:none,那麼show呢?

display:block不就行了嗎?這樣確實可以將元素顯示出來。但是萬一元素原來的值是display:inline呢?

那在hide處儲存原來的值不就行了嗎?就像以下的代碼:

node.oldDisplay = getDisplay(node); 

要是執行show前沒有不執行hide呢?比如下面這種情況,不就沒有oldDisplay了嗎(⊙0⊙)

<style>div{ display:none; }</style><div>display:none</div>$('div').show() 

好,關鍵的地方到了:我們擷取元素display的預設值就可以了吧?比如div預設是block,span預設是inline。

思路有了,那麼接下來的問題是:如何擷取元素display的預設值

嘿嘿嘿,想不到吧?這裡需要用點小技巧,大體思路如下:通過nodeName建立一個新的標籤,再擷取。

有個地方可以再最佳化一下,getDisplay擷取到元素display預設值後,可以使用jQuery的cache機制存起來(實際上jQuery也是這麼做了)。

function getDisplay(node){var display = window.getComputedStyle(node, null).getPropertyValue('display');if(display === 'none'){var dom = document.createElement(node.nodeName);//插入到body中document.body.appendChild(dom);//即可擷取到元素display的預設值var display = window.getComputedStyle(dom, null).getPropertyValue('display');document.body.removeChild(dom);}return display;}

然後,綜合這兩種情況:

//有oldDispaly則設定if(node.oldDisplay) node.style.display = node.oldDisplay;//沒有則設定為元素預設值或元素當前值else node.style.display = getDisplay(node); 

以為這樣就結束了?NO,show函數的情況還是挺複雜的,我們大致要應對這幾種情況:

<style>#none,#none2{ display: none; }</style><body><div id="div">預設值為block</div><span id="span">預設值為inline</span><div id="div2" style="display:inline-block;">修改為inline-block</div><div id="none">通過css隱藏了</div><div id="none2" style="display:none">通過css和style隱藏了</div></body> 

最終,show函數變成了這鬼樣ψ(╰_╯)。大致思路如下:

show: function(){Array.prototype.forEach.call(this, function(node){//if(node.style) continue; //textnode沒有style//刪除style上的display:nonevar display = node.style.display;if(display === 'none'){//dispaly置為空白後,css如果有display則css的生效//否則預設的生效node.style.display = '';}//元素display值為非預設值情況,需要還原為oldDisplay:div->display:inline-block//或 檢測css上的display是否為noneif(node.style.display==='' || isHidden(node)){//有oldDispaly則設定if(node.oldDisplay) node.style.display = node.oldDisplay;//沒有則設定為元素預設值或當前值else node.style.display = getDisplay(node);}})} 

--------------------------

鏈式調用就是類似這種情況:

$('div').show().hide().css('height','300px').toggle()

實現起來非常簡單,只要在每個函數後面return this即可

--------------------------

有同學說:喂!這個show,hide不對吧?是不是漏了時間參數? 用setTimeOut自己實現吧~>_<~+。

本節最主要是讓大家知道jQuery需要考慮的情況非常多(很多髒活)。即時簡化了代碼,依然還是這麼長。

寫完後,發現show還有一種情況沒考慮:

div{ display:none !important; }<div>大家自己開腦洞,怎麼處理吧(⊙0⊙)</div>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.