【发布时间】:2010-05-13 15:29:30
【问题描述】:
jQuery find(..) 遍历方法不包括当前节点——它从当前节点的子节点开始。调用在其匹配算法中包含当前节点的查找操作的最佳方法是什么?浏览文档时,没有任何东西会立即跳出来。
【问题讨论】:
标签: jquery
jQuery find(..) 遍历方法不包括当前节点——它从当前节点的子节点开始。调用在其匹配算法中包含当前节点的查找操作的最佳方法是什么?浏览文档时,没有任何东西会立即跳出来。
【问题讨论】:
标签: jquery
对于 jQuery 1.8 及更高版本,您可以使用.addBack()。它需要一个选择器,因此您不需要过滤结果:
object.find('selector').addBack('selector')
在 jQuery 1.8 之前,您一直使用 .andSelf(),(现已弃用并删除),然后需要过滤:
object.find('selector').andSelf().filter('selector')
【讨论】:
'selector' 两次,这使得封装更加可取。 YMMV
'selector' 两次,(如@ronen 所述),你不能只使用object.parent().find('selector')吗? ——话虽如此,我喜欢为你做的 lib 的想法。
object.parent().find('selector') 包括object 的兄弟姐妹及其后代。
你不能直接这样做,我能想到的最接近的是使用.andSelf()并调用.filter(),像这样:
$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);
很遗憾.andSelf() 没有选择器,这很方便。
【讨论】:
closest(..) 包括当前的 DOM 元素并在树上向上,而像 find(..) 等所有向下遍历的方法都与当前元素不匹配。当两个操作一起用于完整的垂直搜索时,就好像 jQuery 团队有目的地实现了这些,以免重叠。
定义
$.fn.findSelf = function(selector) {
var result = this.find(selector);
this.each(function() {
if ($(this).is(selector)) {
result.add($(this));
}
});
return result;
};
然后使用
$.findSelf(selector);
而不是
$find(selector);
遗憾的是 jQuery 没有这个内置的。这么多年的发展真的很奇怪。由于 .find() 的工作方式,我的 AJAX 处理程序未应用于某些顶级元素。
【讨论】:
filter(),这更有意义。
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))
您可以将$('selector') 存储在变量中以加快速度。如果您非常需要,您甚至可以为此编写自定义函数:
$.fn.andFind = function(expr) {
return this.find(expr).add(this.filter(expr));
};
$('selector').andFind('otherSelector')
【讨论】:
$('selector').find('otherSelector').add($('otherSelector')),你现在拥有的是.andSelf()。最后,.andFind() 不会根据表达式进行过滤,您需要 .add($(this).filter(expr)) :)
$('selector') 是否被其他获取 jQuery 对象的方法替换并不重要(如果这就是您不以选择器开头的意思),add() 可以像 $() 一样处理任何事情。
$('selector') 可能是$('selector').children('filter').closest('.class').last()...它可能在一个链中,你不知道你要添加的对象是什么,所以通用解决方案应该采取像过滤器一样的前一个对象:)
this 是调用插件的任何 jQuery 对象。它也可能是调用链的结果。
接受的答案非常低效,会过滤已经匹配的元素集。
//find descendants that match the selector
var $selection = $context.find(selector);
//filter the parent/context based on the selector and add it
$selection = $selection.add($context.filter(selector);
【讨论】:
如果您希望链接正常工作,请使用下面的 sn-p。
$.fn.findBack = function(expr) {
var r = this.find(expr);
if (this.is(expr)) r = r.add(this);
return this.pushStack(r);
};
在调用结束函数后,它返回#foo 元素。
$('#foo')
.findBack('.red')
.css('color', 'red')
.end()
.removeAttr('id');
如果不定义额外的插件,你就会陷入困境。
$('#foo')
.find('.red')
.addBack('.red')
.css('color', 'red')
.end()
.end()
.removeAttr('id');
【讨论】:
this 是多个元素this.is() 已经满足如果只有一个匹配。
如果您正在寻找恰好一个元素,无论是当前元素还是其中的一个,您可以使用:
result = elem.is(selector) ? elem : elem.find(selector);
如果您正在寻找多个元素,您可以使用:
result = elem.filter(selector).add(elem.find(selector));
andSelf/andBack 的使用非常罕见,不知道为什么。也许是因为我之前提到的一些人的性能问题。
(我现在注意到 Tgr 已经给出了第二种解决方案)
【讨论】:
我知道这是一个老问题,但有一个更正确的方法。如果顺序很重要,例如当您匹配 :first 之类的选择器时,我编写了一个小函数,它将返回与 find() 实际包含当前元素集完全相同的结果:
$.fn.findAll = function(selector) {
var $result = $();
for(var i = 0; i < this.length; i++) {
$result = $result.add(this.eq(i).filter(selector));
$result = $result.add(this.eq(i).find(selector));
}
return $result.filter(selector);
};
无论如何它不会有效率,但这是我想出的最好的维持正确秩序的方法。
【讨论】:
【讨论】:
如果您严格查看当前节点,您只需这样做
$(html).filter('selector')
【讨论】:
我试图找到一个不会重复的解决方案(即不要两次输入相同的选择器)。
这个小小的 jQuery 扩展做到了:
jQuery.fn.findWithSelf = function(...args) {
return this.pushStack(this.find(...args).add(this.filter(...args)));
};
它结合了find()(仅后代)和filter()(仅当前集)并支持两者都吃的任何参数。 pushStack() 允许 .end() 按预期工作。
这样使用:
$(element).findWithSelf('.target')
【讨论】:
这是正确(但可悲)的事实:
$(selector).parent().find(oSelector).filter($(selector).find('*'))
【讨论】:
$(selector) 本身。