如今移動端項目在重構階段,將以前的jQuery所有替換成Zepto了。因爲Zepto的精簡,以置於以前的jQuery的代碼不能運行了,其中visible選擇器就是其中一個。既然已經選擇了Zepto,那就給Zepto增長visible功能。javascript
第一反應就是思考經過元素的屬性來判斷,而後嘗試了使用display和visibility來進行判斷。可是通過小的測試,是我想的簡單了!css
display是沒法繼承父元素的,visibility是可以繼承父元素,可是父元素採用的是display顯示與隱藏。html
既然模塊的根元素是用display顯示與隱藏,那我先就經過類選擇器,選到元素。而後再透過遞歸判斷父元素display,直到body元素。git
;(function($) { var _filter = $.fn.filter; function visible(elem) { var $elem = $(elem); if($elem.css('display') === 'none') { return false; }else { if($elem.is('body')) { return true; }else { if(visible($elem.parent())) { return true; } } } } $.fn.filter = function(sel) { if (sel === ":visible") { return $([].filter.call(this, visible)); } return _filter.call(this, sel); }; })(window.Zepto);
本身的實現是能夠的,不過自我感受有點饒了,看看能不能透過其它方式來解決。github
查看了jQuery3.0的內部實現,最終調用的是jQuery.expr.filters.visible瀏覽器
jQuery.expr.filters.visible = function( elem ) { return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); };
jQuery首先的判斷元素的offsetWidth和offsetHeight。由於根元素隱藏後,致使其子元素的寬高爲0。不佔用文檔流,這很好理解。ide
getClientRects:獲取元素佔據頁面的全部矩形區域,用於獲取元素佔據頁面的全部矩形區域
與之相關的是getBoundingClientRect。
getBoundingClientRect:用於得到頁面中某個元素的左,上,右和下分別相對瀏覽器視窗的位置學習
而爲何要使用這個呢?在官網找到了答案。測試
Breaking change: Behavior of :hidden and :visible
An element is considered now visible if it has a layout box returned from the DOM getClientRects() method,even if that box has a height and/or width of zero. This means that elements such as
or an empty <span> element that don't have height are considered to be visible.
大致的意思是對於一個元素自己寬高都爲0,可是佔據了穩定流,這是能認爲是visible的。好比像 換行br、空的span 標籤。
在github上也找到了,對Zepto增長visible的方法。
;(function($){ var _is = $.fn.is, _filter = $.fn.filter; function visible(elem){ elem = $(elem); return !!(elem.width() || elem.height()) && elem.css("display") !== "none"; } $.fn.is = function(sel){ if(sel === ":visible"){ return visible(this); } if(sel === ":hidden"){ return !visible(this); } return _is.call(this, sel); } $.fn.filter = function(sel){ if(sel === ":visible"){ return $([].filter.call(this, visible)); } if(sel === ":hidden"){ return $([].filter.call(this, function(elem){ return !visible(elem); })); } return _filter.call(this, sel); } })(Zepto);
最終我選擇了最後一種,功能可以知足現有的需求。
其實Sizzle很強大,這visible選擇器只是其九牛一毛,後面能夠再學習學習其思想。
原文地址http://xiaoqiang730730.github.io/2016/07/16/visible%E9%80%89%E6%8B%A9%E5%99%A8/