0
点赞
收藏
分享

微信扫一扫

深入学习jquery源码之has()和closest()


深入学习jquery源码之has()和closest()

has(expr|ele)

概述

保留包含特定后代的元素,去掉那些不含有指定后代的元素。

.has()方法将会从给定的jQuery对象中重新创建一组匹配的对象。提供的选择器会一一测试原先那些对象的后代,含有匹配后代的对象将得以保留。

参数

expr String

一个选择器字符串。

element DOMElement

一个DOM元素

给含有ul的li加上背景色

<ul>
<li>list item 1</li>
<li>list item 2
<ul>
<li>list item 2-a</li>
<li>list item 2-b</li>
</ul>
</li>
<li>list item 3</li>
<li>list item 4</li>
</ul>

$('li').has('ul').css('background-color', 'red');

 

closest(expr,[context]|object|element)

概述

jQuery 1.3新增。从元素本身开始,逐级向上级元素匹配,并返回最先匹配的元素。。

closest会首先检查当前元素是否匹配,如果匹配则直接返回元素本身。如果不匹配则向上查找父元素,一层一层往上,直到找到匹配选择器的元素。如果什么都没找到则返回一个空的jQuery对象。

closest和parents的主要区别是:1,前者从当前元素开始匹配寻找,后者从父元素开始匹配寻找;2,前者逐级向上查找,直到发现匹配的元素后就停止了,后者一直向上查找直到根元素,然后把这些元素放进一个临时集合中,再用给定的选择器表达式去过滤;3,前者返回0或1个元素,后者可能包含0个,1个,或者多个元素。

closest对于处理事件委托非常有用。

参数

expr String,Array

用以过滤元素的表达式。jQuery 1.4开始,也可以传递一个字符串数组,用于查找多个元素。

expr,[context] String

expr:用以过滤子元素的表达式

context:DOM元素在其中一个匹配的元素可以被发现。如果没有上下文在当时的情况下通过了jQuery设置将被使用。

jQuery object  object

一个用于匹配元素的jQuery对象

element DOMElement

一个用于匹配元素的DOM元素。

展示如何使用clostest查找多个元素

<ul><li></li><li></li></ul>

$("li:first").closest(["ul", "body"]);

[ul, body]

展示如何使用clostest来完成事件委托。

<ul>
<li><b>Click me!</b></li>
<li>You can also <b>Click me!</b></li>
</ul>

$(document).bind("click", function (e) {
$(e.target).closest("li").toggleClass("hilight");
});

 

jquery源码

jQuery = function (selector, context) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init(selector, context);
}

init = jQuery.fn.init = function (selector, context) {

}

var rneedsContext = jQuery.expr.match.needsContext;
var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
var risSimple = /^.[^:#\[\.,]*$/;

jQuery.filter = function (expr, elems, not) {
var elem = elems[0];

if (not) {
expr = ":not(" + expr + ")";
}

return elems.length === 1 && elem.nodeType === 1 ?
jQuery.find.matchesSelector(elem, expr) ? [elem] : [] :
jQuery.find.matches(expr, jQuery.grep(elems, function (elem) {
return elem.nodeType === 1;
}));
};

rnative = /^[^{]+\{\s*\[native \w/
hasCompare = rnative.test(docElem.compareDocumentPosition);

// Element contains another
// Purposefully does not implement inclusive descendent
// As in, an element does not contain itself
contains = hasCompare || rnative.test(docElem.contains) ?
function (a, b) {
var adown = a.nodeType === 9 ? a.documentElement : a,
bup = b && b.parentNode;
return a === bup || !!(bup && bup.nodeType === 1 && (
adown.contains ?
adown.contains(bup) :
a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
));
} :
function (a, b) {
if (b) {
while ((b = b.parentNode)) {
if (b === a) {
return true;
}
}
}
return false;
};


jQuery.fn.extend({
has: function (target) {
var i,
targets = jQuery(target, this),
len = targets.length;

return this.filter(function () {
for (i = 0; i < len; i++) {
if (jQuery.contains(this, targets[i])) {
return true;
}
}
});
},

closest: function (selectors, context) {
var cur,
i = 0,
l = this.length,
matched = [],
pos = rneedsContext.test(selectors) || typeof selectors !== "string" ?
jQuery(selectors, context || this.context) :
0;

for (; i < l; i++) {
for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) {
// Always skip document fragments
if (cur.nodeType < 11 && (pos ?
pos.index(cur) > -1 :

// Don't pass non-elements to Sizzle
cur.nodeType === 1 &&
jQuery.find.matchesSelector(cur, selectors))) {

matched.push(cur);
break;
}
}
}

return this.pushStack(matched.length > 1 ? jQuery.unique(matched) : matched);
}
});

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

举报

相关推荐

0 条评论