matchesSelector及低版本IE中對該方法的實現


matchesSelector用來匹配dom元素是否匹配某css selector。它為一些高級方法的實現提供了基礎支持,比如事件代理,parent, closest等。

W3C在2006年就提出了該方法草案,Firefox和Safari相繼實現,比如

<div id="wraper" class="item"></div>
<script>
    wraper.mozMatchesSelector('div') // true 標簽選擇器
    wraper.mozMatchesSelector('#wraper') // true id選擇器
    wraper.mozMatchesSelector('.item') // true 類選擇器
</script>

  

目前除IE6-IE8,Firefox/Chrome/Safari/Opera/IE 的最新版本均已實現,但方法都帶上了各自的前綴

Chrome/Safari

 

Firefox

 

IE9+

 

可以用特性監測來獲取一個統一接口API。如下

var matchesSelector = function() {
    var body = document.body
    return body.webkitMatchesSelector || body.msMatchesSelector || body.mozMatchesSelector || body.oMatchesSelector
}()

有幾個細節

1.  優先使用body.webkitMatchesSelector webkit內核占有率最高,尤其國內國產瀏覽器的高速引擎是webkit

2.  這里沒有優選獲取body.matchesSelector,是因為該方法迄今尚未標准化

3.  2013年2月Opera放棄Presto轉向Webkit,因此把body.oMatchesSelector放在了最后以兼容老版本的Opera

 

對於低版本的IE,如何實現該方法嗎? 首先需要實現一個基本的CSS選擇器,這里提供了一個常用選擇器(id,class,tagName,attribute)的實現。

 

兩種情況

1. 對於已經存在於頁面里的DOM元素

function matches(el, selector) {
	var parent = el.parentNode
	var match = query(selector, parent)
    var len = match.length
    if (len) {
        while (len--) {
            if (match[len] == el) {
                return true
            }
        }
        return false
    } else {
        return false
    }
}

存在於頁面的DOM元素,必定有parentNode,緊接着在父節點里查找指定的selector,如果不存在返回false,如果存在還有過濾下,如果匹配的元素和傳入的el是同一個元素則返回true。

 

2. 對於動態創建的元素,尚未添加到頁面中

function matches(el, selector) {
	var tempParent = document.createElement('div')
	tempParent.appendChild(el)
    match = query(selector, tempParent)
    tempParent.removeChild(el)
    return !!match.length
}

var pp = document.createElement('p')
pp.id = 'pp'
pp.className = 'pp1'
pp.setAttribute('data-info', 'Jack')
pp.innerHTML = 'test'

matches(pp, 'p') // true
matches(pp, '#pp') // true
matches(pp, '.pp1') // true
matches(pp, '[data-info=jack]') // true

此時該元素師沒有父元素的,這里創建了一個臨時的父元素,添加子元素后再把它刪掉。剩余思路同上。

 

兩種情況合並一起就完成了對IE9-版本瀏覽器的支持

function matches(el, selector) {
	var parent = el.parentNode
	var match = query(selector, parent)
    var len = match.length

    if (parent) {
	    if (len) {
	        while (len--) {
	            if (match[len] == el) {
	                return true
	            }
	        }
	        return false
	    } else {
	        return false
	    }
    } else {
		var parent = document.createElement('div')
		parent.appendChild(el)
	    match = query(selector, parent)
	    parent.removeChild(el)
	    return !!match.length 	
    }
}

 

最后是一個完成版本

var matchesSelector = function() {
    var body = document.body
    var w3cMatches = body.webkitMatchesSelector || body.msMatchesSelector || body.mozMatchesSelector || body.oMatchesSelector
    
	function matches(el, selector) {
		return w3cMatches.call(el, selector)
	}

	function lowIEMatches(el, selector) {
		var parent = el.parentNode
		var match = query(selector, parent)
	    var len = match.length

	    if (parent) {
		    if (len) {
		        while (len--) {
		            if (match[len] == el) {
		                return true
		            }
		        }
		        return false
		    } else {
		        return false
		    }
	    } else {
			var parent = document.createElement('div')
			parent.appendChild(el)
		    match = query(selector, parent)
		    parent.removeChild(el)
		    return !!match.length 	
	    }
	}

	return w3cMatches ? matches : lowIEMatches
}()

  

 

相關:

http://dev.w3.org/2006/webapi/selectors-api2/#matchtesting

https://developer.mozilla.org/zh-CN/docs/Web/API/Element.matches

http://msdn.microsoft.com/en-us/library/ie/ff975201(v=vs.85).aspx

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM