sizzle分析记录:关于querySelectorAll兼容问题
querySelector和querySelectorAll是W3C提供的新的查询接口
目前几乎主流浏览器均支持了他们。包括 IE8(含) 以上版本、 Firefox、 Chrome、Safari、Opera。
万能的sizzle在高版本的浏览器中复杂的选择器尽量走querySelectorAll,前提是这个匹配的节点没有兼容问题
从IE8开始虽然支持querySelectorAll的API,但是会有各式各样的BUG,所以sizzle拿rbuggyQSA用来记录这个BUG问题
if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
//newContext.querySelectorAll( newSelector )
}
zepto的选择器则更直接
zepto.qsa = function(element, selector) {
var found
return (isDocument(element) && idSelectorRE.test(selector)) ?
((found = element.getElementById(RegExp.$1)) ? [found] : []) :
(element.nodeType !== 1 && element.nodeType !== 9) ? [] :
slice.call(
classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
element.querySelectorAll(selector)
)
}
sizzle 2000行,zepto直接querySelectorAll接口,利弊各自评估了
重点就看querySelectorAll的坑到底有哪些?
接口定义:
partial interface Document {
Element? querySelector(DOMString selectors);
NodeList querySelectorAll(DOMString selectors);
}; partial interface DocumentFragment {
Element? querySelector(DOMString selectors);
NodeList querySelectorAll(DOMString selectors);
}; partial interface Element {
Element? querySelector(DOMString selectors);
NodeList querySelectorAll(DOMString selectors);
};
从接口定义可以看到Document、DocumentFragment、Element都实现了NodeSelector接口。即这三种类型的元素都拥有者两个方法。
querySelector和querySelectorAll的参数须是符合css selector 的字符串。
不同的是querySelector返回的是一个对象,querySelectorAll返回的一个集合(NodeList)。
所以选择querySelectorAll更符合jQuery这个合集对象的习惯
document.querySelectorAll 与 element.querySelectorAll区别?
当调用上下为document的时候,没有什么问题,各浏览器的实现基本一致
如果调用的上下文是element,dom Node的时候,浏览器的实现有点不同
具体就是表现在:element.querySelectorAll 在文档内找全部符合选择器描述的节点包括Element本身
<div class= "aaron" id= "aaronId" >
<p><span>内容</span></p>
<div class="text">452</div>
</div>
js
<script type="text/javascript"> var aaElement = document.getElementById('aaronId');
var element = aaElement.querySelector('.aaron span');
var elementList = document.querySelectorAll('.aaron span');
console.log(element); // <span>Test</span>
console.log(elementList); //
问题出在testElement.querySelector尽然还有返回值!选择上下文是在aaElement里面,选择器是.aaarn就父节点,理论是找不到对应的节点的
所以逻辑上是不合理的,因为根本找不到,但是结果跟document调用如出一辙,所以此时node ele类似document 了
可能的查找机制是这样的:首先在document的范围内进行查找所有满足选择器条件的元素,
在上面这段代码中,我们的选择器是.aaron span,就是所有的直接父元素类名为aaron的元素。
然后,再看哪些元素是调用querySelector/querySelectorAll的元素的子元素,这些元素将会被返回
这也就说明了为什么aaElement会一同返回
那么针对这种情况如何兼容?
程序员的智慧总是无穷的, Andrew Dupont提出了一个解决方案,来自jQuery2.1.1
先看看jQuery最终的实现newContext.querySelectorAll用的上下文调用
if ( newSelector ) {
try {
push.apply( results,
newContext.querySelectorAll( newSelector )
);
return results;
} catch(qsaError) {
} finally {
if ( !old ) {
context.removeAttribute("id");
}
}
}
代码可见newContext可能是document || 提供的一个上下文
如:$("#aaronId").find("div[class='text']) 此时的上下文即是$("#aaronId")节点
jQuery(element).find(selector) 在文档内找全部符合选择器描述的节点不包括Element本身
注意finally总是执行context.removeAttribute("id"),意味着我们在之前的处理强制加了一个id
反推hack的手法,selectors前面指定上下文的的id,限制匹配的范围
版本各有实现的不同,但是我们目前最终版为标准2.1.1
IE 8 :不支持上下文为object;
if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
groups = tokenize( selector ); if ( (old = context.getAttribute("id")) ) {
nid = old.replace( rescape, "\\$&" );
} else {
context.setAttribute( "id", nid );
}
nid = "[id='" + nid + "'] "; i = groups.length;
while ( i-- ) {
groups[i] = nid + toSelector( groups[i] );
}
newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
newSelector = groups.join(",");
}
1. 关键是给context设置一个id
所以上下文content,就会存在这个id限制范围
2. 拼接出查询的选择器,附上这个ID前缀
newSelector: "[id='sizzle-1405486760710'] div[class='text']"
3. 查询
newContext.querySelectorAll( newSelector )
4. 因为强制加了ID,所以需要删除
context.removeAttribute("id");
这样就达到目的范围限制:context.querySelectorAll了
querySelectorAll在选择器上存在的问题,具体我是看jQuery的源码相关处理,基本都是IE8上的问题
jQuery对兼容的判断,都是采用的功能判断直接特性检测,伪造一个真实的环境测试支持度
针对querySelectorAll选取存在的问题之后分析
sizzle分析记录:关于querySelectorAll兼容问题的更多相关文章
- sizzle分析记录:词法分析器(tokenize)
词法分析器(tokenize)? 词法分析器又称扫描器.词法分析是指将我们编写的文本代码流解析为一个一个的记号,分析得到的记号以供后续语法分析使用. sizzle引入了tokenize这个概念,意义? ...
- sizzle分析记录:getAttribute和getAttributeNode
部分IE游览器下无法通过getAttribute取值? <form name="aaron"> <input type="text" name ...
- sizzle分析记录:属性选择器
源码部分 通过Sizzle.attr匹配出值 然后通过表达式刷选计算 "ATTR": function( name, operator, check ) { return func ...
- sizzle分析记录:分解流程
<form> <label>Name:</label> <input name="name" /> <fieldset> ...
- sizzle分析记录: 自定义伪类选择器
可见性 :hidden :visible 隐藏对象没有宽高,前提是用display:none处理的 jQuery.expr.filters.hidden = function( elem ) { // ...
- Fine报表权限流程分析记录
Fine报表权限流程分析记录 URL访问三种类型的报表:第一个:BI报表 例如: http://192.25.103.250:37799/WebReport/ReportServer?op=fr_bi ...
- PostgreSQL的基础数据类型分析记录-转
src:http://www.codeweblog.com/postgresql%E7%9A%84%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E ...
- 获取登录验证码失败及前后端不同域导致session丢失问题分析记录
前言 前两周在把兄弟公司的几个服务部署到我们公司测试环境服务器的时候又遇到了不少问题,因为是前后端分离的项目,所以这次也同样遇到了跨域问题,解决方式也跟上一回的不一样,这里就再来分析记录一下. 登录验 ...
- 记录各种IE兼容问题,IE6,IE7,IE8,IE9,IE10
记录遇到的IE BUG: 1.IE8开发者工具打不开 解决办法:IE8新增了开发人员工具,非常不错,比早期的DevToolbar好用多了.不过在我的Win7下 使用的时候偶尔会出现一个莫名其妙的问 ...
随机推荐
- UVALive-4839 HDU-3686 Traffic Real Time Query System 题解
题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...
- DB2数据库参数建议(AIX)
修改用户最大进程数: chdev -l sys0 -a maxuproc=' 用户资源配置:对实例用户,fence用户,应用用户添加如下限制: db2inst1 : fsize=- fsize_har ...
- 【逆向篇】分析一段简单的ShellCode——从TEB到函数地址获取
其实分在逆向篇不太合适,因为并没有逆向什么程序. 在http://www.exploit-db.com/exploits/28996/上看到这么一段最简单的ShellCode,其中的技术也是比较常见的 ...
- Android历史版本Logo
Android操作系统是一个由Google和开放手持设备联盟共同开发发展的移动设备操作系统,其最早的一个版本Android 1.0 beta发布于2007年11月5日,至今已经发布了多个更新. ...
- 微信第三方平台定时接收component_verify_ticket
背景: 获取第三方平台令牌(component_access_token),增加了component_verify_ticket参数.component_verify_ticket由公众平台每隔10分 ...
- ThreadPoolExecutor源码学习(2)-- 在thrift中的应用
thrift作为一个从底到上除去业务逻辑代码,可以生成多种语言客户端以及服务器代码,涵盖了网络,IO,进程,线程管理的框架,着实庞大,不过它层次清晰,4层每层解决不同的问题,可以按需取用,相当方便. ...
- 利用DOS批处理实现定时关机操作
10月1放假回来,寝室晚上10:30就停电了,最无法让人理解的是第二天早上8:00才来电.原来晚上电脑都是不关机的,开着WiFi一直到天亮,可是现在不行了,电脑如果一直开着第二天早上起来电脑肯定没电, ...
- JQuery的父、子、兄弟节点查找方法
jQuery.parent(expr) //找父元素 jQuery.parents(expr) //找到所有祖先元素,不限于父元素 jQuery.children ...
- myeclipse tomcat内存溢出解决方法
Tomcat直接启动正常,通过myeclipse启动tomcat内存溢出.MyEclipse启动Tomcat无视catalina.bat中设置内存大小的问题.在 tomcat的catalina.bat ...
- 整理一自己不怎么熟悉的HTML标签(会陆续更新)
---恢复内容开始--- 小白刚开始接触HTML和CSS,在学习过程中发现又遇到很多不认识的标签,于是就想把他们都记录下来,一来可加深记忆,二来也方便以后查阅,当然如果能帮助到你们也是很开心的啦! 1 ...