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