Jquery选择器与CSS选择器非常相似,CSS选择器提供诸多功能,同时两者在解析上均采用从右向左解析,因为在建立Render Tree时,若采用自左向右解析,没词匹配不成功均需要退回再进行匹配,而反向解析利用排除法,逐步缩小元素候选集,优化了从子元素找父元素的过程,对于大量元素很有效(所以采用通配符很低效)
CSS的基础选择器:
群组选择器:selector1, selector2, selector3...
简单选择器:ID" #id ",标签" tag ",类" .class ",属性“ [att , att=val , att~=val , att|=val , att^=val , att*=val , att$=val] ”,通配符“ * ”
关系选择器:孩子“parent > child”,后代“ancestor descendant”,相邻“prev + next”,兄弟“prev ~sibling”
伪类选择器:动作伪类,目标伪类,语言伪类,状态伪类,结构伪类,取反伪类 (伪类采用筛选器,基本、内容、可见、子元素、表单筛选器)
普通接口兼容性:
关于属性attributes:IE8前必须使用getAttribute(‘className‘),而其余为getAttribute(‘class‘)
关于getElementById:IE8之前不区分ID大小写,且无法识别重名的表单name和ID
关于getElementByTagName:IE6-8会将注释节点纳入通配符的选择范围,需要递归判断nidetype=1才可取
关于getElementByClassName:IE不支持此方法
//为通配符做兼容性处理
function byTagName(tag, context) {
var ele,
tmp=[],
index = 0,
resulrs = context.getElementByTagName(tag);
if(tag === "*") {
while((ele = result[index++])) {
if(ele.nodetype === 1) {
tmp.push(ele);
}
}
return tmp;
}
return results;
};
//getElementsByClassName
function getClassNames(tagName, classStr) {
var nodes = document.getElementsByTagName(tagName),
ret = [];
for (i = 0; i < nodes.length; i++) {
if (hasClass(nodes[i], classStr)) {
ret.push(nodes[i])
}
}
return ret;
}
function hasClass(tagStr, classStr) {
var arr = tagStr.className.split(/\s+/); //class可以有多个
for (var i = 0; i < arr.length; i++) {
if (arr[i] == classStr) {
return true;
}
}
return false;
}
高级接口querySelector:
querySelector返回一个集合,element.querySelectorAll返回集合(nodelist)其中包括element本身,这两个选择器无论之前调用的上下文element如何,总是在document范围内查找所有满足的元素,其次查找上句中得到的元素集合中符合子元素,返回这些元素,于是自然包括element元素,这也解释了为何element元素会被返回
高级接口兼容性:
前文提到querySelectorAll无视上下文,始终在document中查找,这导致返回element本身,针对这个问题,采用Andrew Dupont方法加以修复 - 利用临时添加的ID显示范围,并在使用后删除,如下
var context = document.querySelector(‘.aaron‘);
var old;
var nid = Math.random();
//是否有ID/‘|\\/g
if ((old = context.getAttribute("id"))) {
nid = old.replace(/‘|\\/g, "\\$&");
} else {
context.setAttribute("id", nid);
}
nid = "[id=‘" + nid + "‘] ";
var newSelector = nid + ‘.aaron span‘;
if (newSelector) {
try {
alert(context.querySelectorAll(newSelector).length)
} catch (qsaError) {} finally {
//如果是通过增加的范围,则要删除
if (!old) {
context.removeAttribute("id");
}
}
}
源代码分析系列:
~ing
参考 慕课网:https://www.imooc.com/learn/172
博客园:https://www.cnblogs.com/chuaWeb/p/jQuery-1-9-1-jQuery-selector1.html