javascript jquery '.find()'与':not'选择器一起使用时缺少某些元素(选择器受'.find()'调用元素的影响,但它不应该受到影响)

ecfdbz9o  于 2023-01-07  发布在  Java
关注(0)|答案(2)|浏览(242)

问题

我有一个元素$(elt_Main)<span id="a">
我在上面调用$(elt_Main).find(selector);
带选择器selector = ':not(span span)';
但是jquery**没有给出我想要的所有子元素。

示例[测试1.html]

  • 假设html中的内容是::
<body>
<span id="a">The first <span class="red">signature <span class="green">for the .find() <span class="blue">method accepts</span> a selector</span> <strong>expression</strong> of the <span class="green">same type that we can pass to the</span> $() function</span>. The <span class="red">elements</span> will be filtered by testing whether they match this selector; all parts of the selector <strong>must lie inside of an element</strong> on which .find() is called.</span>
</body>
  • 该javascript是::
let elt_Main = document.getElementById('a');
  // ...
  html_ResultAppend += hr_3;
  selector = ':not(span span)';         // <<< watch
  jqElt = $(elt_Main).find(selector);   // <<< watch
  • 提供调试输出的js是::
for (let o of jqElt) {
    html_ResultAppend += hr_4;
    html_ResultAppend += o.outerHTML;
  }
  • jqElt的结果将是::
<strong>expression</strong>
<strong>must lie inside of an element</strong>
  • 预期结果应为::
<span class="red">signature <span class="green">for the .find() <span class="blue">method accepts</span> a selector</span> <strong>expression</strong> of the <span class="green">same type that we can pass to the</span> $() function</span>
<span class="red">elements</span>
<strong>expression</strong>
<strong>must lie inside of an element</strong>
  • PB &原因是:
    • 缺少这2个元素**
<span class="red">signature <span class="green">for the .find() <span class="blue">method accepts</span> a selector</span> <strong>expression</strong> of the <span class="green">same type that we can pass to the</span> $() function</span>
<span class="red">elements</span>
  • (我认为)jquery的逻辑是(这是错误的)::

<span id="a"> <span class="red">signature ...

  • <span class="red">signature ...位于跨度<span id="a">
  • 〉我们说:not(span span)
  • 〉因此不应选择此选项
    (^与上述<span id="a"> <span class="red">elements</span>相同)
  • 我的逻辑是:

<span id="a">$(elt_Main))是调用.find()的元素

    • 当我们在.find()中使用css选择器时,<span id="a">$(elt_Main))本身不应 * 被考虑/播放任何效果**
  • 否则,在下面的例子中就没有任何意义了:

比如说我们这样做$(elt_Main).find('span');
这应该只找到elt_Main子元素,它是span--这是正确的。
如果我们在使用use selector时考虑到<span id="a">$(elt_Main)),那么这将选择<span id="a">$(elt_Main))本身--这是错误的。

  • 换句话说

.find()<span id="a">$(elt_Main))调用时,
选择器应该将其(要搜索的元素<span id="a">$(elt_Main)))视为标签<span id="a">不存在(--它不应该播放任何效果),并且只在innerHtml上搜索。

证明我的逻辑--示例[test1.html test2.html]

JS选择元素并写入HTML主体。

      • 测试1使用.find() + :not()**
    • 测试2仅使用:not()**

测试2删除了$(elt_Main)中的<span id="a">标签

  • (--正如我上面所说的--我们应该把它当作标签<span id="a">不存在一样)
  • (如果你认为我错了,你说:不要删除<span id="a">,使test1和test2产生相同的结果-〉检查test1和test3--它甚至更糟)
  • 我们清楚地看到

test1输出缺少元素
test2输出正确

(回到问题)

:not选择器一起使用的jquery .find()缺少某些元素(选择器受.find()调用元素影响,但不应受影响)
那么,是jQuery错了吗?还是我错了?为什么?

yeotifhr

yeotifhr1#

好吧,我有一个猜测,所以我只是要张贴它作为一个答案。
正如我在评论中所写的,$(selector).find(selector)基本上像一个两遍过滤器一样工作,它不应该提出任何沙盒式的机制来阻止第二遍选择“检测”候选对象的任何事实/属性,包括但不限于它们的父对象。
然而,我对$(A).find(A B)的怀疑是,它在幕后并不像这样工作:
1.选择A的所有后代
1.从步骤1返回的选择中选择B并且父节点为A的节点(类似于foreach c in S: if c is B and c.parent is A: nS.add(c)
相反,它可能在幕后这样工作:
1.选择A的所有后代
1.从步骤1返回的选择中选择所有A
1.从步骤2返回的选择中选择所有B
如果步骤2没有返回任何元素,那么步骤3也不会返回任何元素。
下面是一个显示“等价物”的示例:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
    <script>
      $("document").ready(function() {
          const a = $("span").find("span").find("span");
          const b = $("span").find("span span");
          const arr = [ a.length, a.get(0).textContent, b.length, b.get(0).textContent ];
          alert(arr.join(" "));
      });
    </script>
  </head>
  <span>A<span>B<span>C</span></span></span>
</html>

我不认为当前实现后代选择器的方式是正确的,我确实想知道jQuery开发人员会如何讨论它(但这实际上只是我的猜测,我还没有检查任何源代码来确保它是100%正确的)。

nfeuvbwi

nfeuvbwi2#

您的选择器要求任何不是其他<span><span>后代的元素。后代测试不仅适用于DOM中起点下的子树(.find()的根元素);它涉及到整个DOM。它必须以这种方式工作。你声称"它不应该"是对选择器工作方式的误解。
因为您的起始元素本身就是<span>,所以子树中的 * 所有 * <span>元素都是<span>的后代,所以它们都不匹配选择器。
您可以尝试使用原生.querySelectorAll()进行测试:

let elt_Main = document.getElementById("a");
let targets = eltMain.querySelectorAll(":not(span span)");

看看你能得到什么。
下面是一个更清楚的示例,使用了一个包含起始点父元素的:not()选择器:
x一个一个一个一个x一个一个二个x
从外部跨度开始,该选择器(:not(.foo span))要求不是<span>且从类"foo"的元素派生的任何元素。起点 * do * 下的所有<span>标记都与:not中的该选择器匹配,因为它们都从父<div>派生。因此,该查询仅找到一个元素,即<b>
一般来说,在一个已经使用了近20年的平台上发现一个严重的错误是相当不可能的,不是不可能,而是不太可能。

相关问题