将复杂的jquery css选择器转换为用于缓存的上下文
在反馈之后,完全重写问题。
我有以下标记:
Title
bla
...
我可以访问:
Title
bla
...
使用:
$('body > *:not(div#do-not-modify-me)');
我这样做,所以我可以得到身体的所有内容,除了具有id“do-not-modify-me”的div。
现在,让我们说我想构建一个函数,让另一个程序员选择正文中的任何东西,就像使用jquery选择一样。 另一个程序员不应该修改div#do-not-modify-me,但他也不应该关心它。
$('body > *:not(div#do-not-modify-me)')
将被调用很多时间,所以我们将缓存它。
这个想法是:
// TEST CODE windows.new_body = $('body > *:not(div#do-not-modify-me)'); function select(selector) { return $(selector, windows.new_body); }
所以其他程序员应该能够做到:
// TEST RESULT CODE select("p").css("color", "red");
它会在身体的所有
中显示红色,但不会包含在div#do-not-modify-me中。
TEST CODE不起作用,因为目前它对上下文结果的子项应用css(),而不是自己的结果。
EG:
select("p").css("color", "red");
表现如下:
$('body > * p :not(div#do-not-modify-me)').css("color", "red");
虽然期望的结果是:
$('body > p :not(div#do-not-modify-me)').css("color", "red");
注意 :
$('body > * :not(div#do-not-modify-me)').parent().css("color", "red");
不起作用,因为
div#do-not-modify-me变成了红色。
您如何在测试结果代码中获得结果? 您可以修改代码的任何部分。
我删除了之前编辑的所有内容,因为它们不再相关,您可以在编辑历史中阅读它们。
EDIT3
基本上问题是你无法缓存选择器。 这是因为$()函数返回匹配的对象,而不是未匹配的对象。 这意味着使用缓存选择器意味着缓存可能与真实DOM不同步。 即在这个简单的页面中:
foo
bar
。
var context = $('body').children(':not(.bar)'); //this holds: foo
bar
$('div', context).append('HAI
'); //context still is foo
bar
even though it should be //foo
bar
HAI
所以你必须每次重做选择,贝司你有两个选择:
//reselect the non-editable area everytime function select(selector) { return $(selector, $('body').children(':not(div#do-not-modify-me)') ); } //or, check the selection against being in the reselectable area. function select(selector){ return $(selector).filter(function(){ return $(this).parents(':not(div#do-not-modify-me)'); }); }
你应该尝试自己哪一个更快。 我不认为有任何其他方法可以确保您不在#do-not-modify-me div中搜索。
你可以做的其他事情,使这更容易(我认为更快)是在div中包装可编辑区域:
Title
那你就可以做到
function select(selector) { return $(selector, $('#modify-me') ); }
你说代码可以以任何方式修改,对吧? 为什么不把它想象成你想要搜索的内容而不是你不想搜索的内容。 将其余代码放在
然后将其用作上下文。 它不会赢得任何优雅奖项,但它很简单并且获得了Job Alone TM 。
我很确定你可以直接使用’context’,如下所示:
context = $('body > *:not(div#do-not-modify-me)'); context.doStuff();
阅读扩展说明后,我会尝试拍摄:
context = $('body > *:not(div#do-not-modify-me)'); $("*:first",context);
你甚至可以这样做:
context = $('body > *:not(div#do-not-modify-me)'); context.find( "*:first");
要获得元素数量,您可以执行以下操作:
var len = context.length;
要访问集合中的元素编号i,您可以使用:
context.get(i);
在api.jquery.com上有大量有用的信息,也读过这个可能你想要创建自己的选择器。
编辑:
之后,我看到了你最近的更新,我认为你正在寻找的是能力迭代上下文结果元素,所以它可以像我在这里提到的那样多次通过:
for ( var i = 0; i < context.length; ++i) { $( context[i]).method( ); // do here you checks, adding, removing. }
这看起来并不聪明,但是应该可行,你可以通过扩展$ .fn并为你的目的实现函数来封装它。 编辑#2:
让我们尝试另一种方式:
(function($) { $.fn.tagName = function( ) { return this.get(0).tagName; }; $.fn.pick = function( tag) { return this.filter( function( ) { return $(this).tagName == tag; }); }; } })(jQuery);
在此之后你可以做contex.pick(“p”),所以它会返回你结果集中的所有段落,但是这段代码是不完整的,所以你需要更多地查看jquery代码,例如在一个jquery代码中实现它你可以使用pick函数使用完整的jqueryfunction,可能你需要考虑使用xpath DOM解析器 。