matchesSelector及低版本IE中对该方法的实现
matchesSelector用来匹配dom元素是否匹配某css selector。它为一些高级方法的实现提供了基础支持,比如事件代理,parent, closest等。
W3C在2006年就提出了该方法草案,Firefox和Safari相继实现,比如
1 2 3 4 5 6 | <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。如下
1 2 3 4 | 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元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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. 对于动态创建的元素,尚未添加到页面中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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-版本浏览器的支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 } } |
最后是一个完成版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
2011-06-03 读jQuery之二(两种扩展)
2011-06-03 读jQuery之一(对象的组成)