关于选择器

wllllll 2011-11-18 09:39:05
关于选择器

最近选择器挺多,感觉这样编程的确很效率。于是研究了下选择器的实现。

研究对象是 司徒正美 发布的选择器包 http://bbs.51js.com/thread-86703-1-1.html

我们先说说选择器的主要技术点:
1. 选择器几乎都首先使用querySelectorAll,如果失败或者不存在这个方法,才会执行内部的动作。

2. 在非IE浏览器下支持:
DOMAttrModified 标签属性修改时
DOMNodeInserted 标签插入时
DOMNodeRemoved 标签删除时

但是document.write所创建的标签是无法被监视的,并且原身文件的HTML也无法被监视。他们只能激发JS操作对象产生的事件。


额外说明:
1 屏蔽querySelectorAll,直接替换所有文件的关键字querySelectorAll


已知明显BUG:
1. querySelectorAll是根据CSS规则来匹配的,如果你的页面中包含多个id,匹配#id, 那么大部分的选择器都会只返回第一个id标签,并且还会导致其他选择器的执行出现结果不正确。
测试:首先必须屏蔽所有querySelectorAll,在 template.html 中写入标签 <div id="title"></div>,这时执行选择器 div[class!=example],除了query所有选择器结果都错误,多了一位。
2. querySelectorAll是根据CSS来匹配的,#title 会返回所有id为 title 的多个标签,选择器有Peppy、query、Sly,结果不统一,支持querySelectorAll就返回多个,不支持就返回第一个。
3. peppy、sizzle选择器在非IE浏览器中,在加载HTML时执行选择器,那么会创建缓存,而将来不激发DOMAttrModified、DOMNodeInserted、DOMNodeRemoved,那么缓存会一直存在,无法获取到HTML后来加载的标签。
4. EXT 对选择器 div ~ p 的匹配结果错误
...全文
148 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
p2227 2011-11-27
  • 打赏
  • 举报
回复
一个id只能连接发三个回复,你发在一起或者发成自己的日志吧
wllllll 2011-11-27
  • 打赏
  • 举报
回复
6. query不支持标签以下所有标签的属性选择器与伪类选择器,如div [href], div :empty
7.yass、inQuery、Sizzle 对div :only-child获得的结果错误,应该获取div以下所有标签是父标签唯一子标签的标签
8. Peppy 对 div:nth-child(-3n+10) 的执行结果错误,yass仅支持div:nth-child(odd)与div:nth-child(even),Sizzle、sky 对(-1n)执行出现无限循环。query在IE下返回的结果也不正确。(-3n+10)应返回序列0-10,并且序列%n返回0的。
9.Peppy、yass、Sizzle、inQuery、EXT 在IE下直接使用选择器获取*,会发生错误,因为IE还返回!DOCTYPE、注译等元素,这些元素缺乏某些属性导致了选择器执行出错,如果其他子标签有注译,那么也会导致*号发生错误。
tg01 2011-11-27
  • 打赏
  • 举报
回复
这是在说什么呢?
sirzxj 2011-11-27
  • 打赏
  • 举报
回复
一个id只能连接发三个回复,你发在一起或者发成自己的日志吧
wllllll 2011-11-21
  • 打赏
  • 举报
回复
已知明显BUG:
5. query , Sizzle, Sly 对重复标签的处理不正确,比如div, .subtoc
默默不得鱼 2011-11-21
  • 打赏
  • 举报
回复
这是要散分的吗
风一样的大叔 2011-11-21
  • 打赏
  • 举报
回复
路过看看
wllllll 2011-11-18
  • 打赏
  • 举报
回复
template.html 文件的测试代码推荐使用以下脚本。

function test(selector) {
try {
var etext = ""

var start = new Date().getTime();
var i = 1;
var fn = functionname.split('.');
var fun = window;
for (var deep = 0; deep < fn.length - 1; deep++)
fun = fun[fn[deep]];

var dadaT = new Date().getTime()
i = 0
while ((++i)) {
var elements = fun[fn[deep]](selector);
if ( new Date().getTime() > (dadaT + 250) ) break
}

var end = (new Date().getTime() - start) / i;
return { 'time': Math.round(end * 1000), 'found': get_length(elements) };
} catch (err) {
if (elements == undefined) elements = { length: -1 };
var end = (new Date().getTime() - start) / i;
return ({ 'time': Math.round(end * 1000), 'found': get_length(elements), 'error': err });
}
}

在非IE浏览器下,如果经常删除标签或者更改标签属性,Peppy和Sizzle的缓存模式几乎无效,执行效率低于其他所有选择器。
而在传统网页环境选择器就是为了快速获取对象并且操作对象,而这两个选择器,只能说他们适合在测试环境下运行,但是不适合在传统环境下运行。并且他们在IE浏览器下的运行效率也不高。

使用以下循环代码进行测试:

while (i++) {
var elements = fun[fn[deep]](selector);
if ( elements.length ) {
elements[0].setAttribute("test", "value")
}
if ( new Date().getTime() > (dadaT + 250) ) break
}


while (i++) {
var elements = fun[fn[deep]](selector);
if ( elements.length ) {
var aElement = document.createElement("DIV");
elements[0].appendChild(aElement)
aElement.parentNode.removeChild(aElement)
}
if ( new Date().getTime() > (dadaT + 250) ) break
}

87,902

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧