【问题标题】:Is the css selector #<my-id> (supposed to be) 100% equivalent to [id=<my-id>] in jQuery?css 选择器#<my-id> (应该是) 100% 等同于 jQuery 中的 [id=<my-id>] 吗?
【发布时间】:2011-08-19 11:56:29
【问题描述】:

一些背景: 我有一个带有显示实体列表的表格的站点。使用 jQuery,我可以单击表中的一行,这将使用 AJAX 加载有关所选实体的一些额外数据。新行将插入到单击行下方的表格中。此行包含有关实体的更多详细信息,并不是真正的行,只是在 HTML 术语中。它包含一大堆数据。当您单击另一行时,当前显示的详细信息行将被隐藏,并显示新单击实体的详细信息行(如果尚未加载,则使用 AJAX 加载)。这里没有问题。

在详细信息行上还有一个选择框。使用 Ajax 加载详细信息行后,我想绑定 select 的 onchange 事件。我做了以下 jQuery 选择:

$("tr.entity_details[data-entity-id=" + entityId + "] select#SelectedDropDownValue")

问题: 这也可以正常工作,除非在一些非常特殊的情况下(我还不能完全定义)。有时它不会选择select 元素。我使用VS2010进行调试,将这两项输入到我的监视窗口中:

$("tr.entity_details[data-entity-id=" + entityId + "] select#SelectedDropDownValue").length
$("tr.entity_details[data-entity-id=" + entityId + "] select[id=SelectedDropDownValue]").length

在第一个没有选择任何东西的情况下,第二个选择。这对我来说真的很奇怪,因为我认为这两个选择器是等价的。

我可以产生这个的情况是: 我的表中有两个实体。

  • 我先点击最下面的:没问题;然后我点击最上面的:没问题。
  • 我先点击最上面的:没问题;然后我点击底部的:问题。

我不知道是什么原因造成的。我在想也许我插入新行并将它们隐藏在javascript中,导致选择有点偏离。但我想那将是一个错误。或者可能与详细信息行包含另一个表并且选择位于该内表中有关。

编辑:

添加更多信息。我在 IE9 和 Chrome 下测试了这个。我正在使用 jQuery 1.5.1 开发一个 ASP.NET MVC 3 应用程序。详细信息行由局部视图生成。在这个局部视图中,我使用 Html Helper DropDownListFor。此帮助程序基于您传递给函数的 C# 属性生成选择元素。它使用属性的名称为元素生成名称和 ID。这会导致页面中的所有选择元素都具有相同的 id。正如一些人已经提到的,这可能就是原因。

【问题讨论】:

  • 您可能需要发布更多代码伙伴 :)
  • 请注意,from the API引号是必需的,在属性等于选择器中。
  • Matthijs,您在什么浏览器和版本中遇到这些问题?
  • 有没有可能有两个具有相同 id 的元素?这可能会导致未定义的行为。
  • 您能否向我们展示您尝试绑定到该元素的方式/位置?

标签: jquery html jquery-selectors css-selectors


【解决方案1】:

我在一个不合规的网站上工作。我们有许多具有相同 ID 的 HTML 元素。我注意到$('#someid') 只抓取它找到的具有该 ID 的第一个元素,而 $('[id="someid"]') 抓取具有该 ID 的所有元素。

【讨论】:

  • @Mully,每个 ID 应该只有 ONE 元素,ID 是唯一的。
  • 嗯,我认为所有“详细信息”行中的选择元素都具有相同的 id。我会在问题中添加一些关于我使用的东西等的更多背景信息。
  • @Neal 我想这就是他所说的“不合规”哈哈
  • 我认为因为我在选择器的第一部分添加了tr.entity_details[data-entity-id=" + entityId + "]",所以在该部分中只有一个具有该 ID 的元素。但我想我应该只选择其他东西。也许添加一个类或选择名称属性(也由 ASP.NET MVC 生成)。
  • #someid[id="someid"] 不同的原因是因为一个是 ID 选择器,它被馈送到 document.getElementById(),而另一个是一个属性选择器,它被馈送到 querySelectorAll(如果不支持,则发出嘶嘶声)。
【解决方案2】:

当遇到一个包含一个ID选择器的选择器字符串时,例如$('#my-id'),jQuery直接将该ID提供给document.getElementById()以获取具有该ID的第一个元素,而无需任何额外步骤。这是well-known and well-documented fact

如果选择器中还有其他内容,jQuery 会完全跳过 document.getElementById() 调用。如果浏览器支持 document.querySelectorAll() 并且选择器是受支持的 CSS 选择器,那么 jQuery 将使用该 API 来查询 DOM,而无需使用自己的引擎 Sizzle。否则,它会服从 Sizzle。

现在,就 CSS 选择器而言,ID 选择器应该始终匹配元素只要它由该 ID 标识,无论 HTML 是否表示拥有多个元素都是无效的同一文档中的此类元素。有关说明,请参阅this answer。我不完全确定 Sizzle 的行为是否相同,但本机实现很可能会如此。当然,由于标记必须无效才能产生影响,所以这不是您应该依赖的。

另一方面,像$('[id=my-id]') 这样的属性选择器具有与ID 选择器相同的语义。这并不意味着“my-id标识的(或任何)元素”;相反,它只是选择具有恰好称为id 的属性的任何元素,其值为my-id。所以在 jQuery 和 CSS 中,不管文档语义如何,它总是匹配任何元素只要它有那个属性和值

也就是说,由于您使用的是 HTML,而 HTML 表示不要识别具有相同 ID 的多个元素,那么正如 cmets 中提到的那样,当您这样做时,可能会发生未定义的行为。在这种情况下,您可以使用属性选择器来保证尽可能多的匹配,但我当然不建议您走这条路。

【讨论】:

    【解决方案3】:

    ID 经常被滥用。如果您正在使用 JavaScript 注入新的 DOM 节点,那么您可能会在某个时刻将节点放在变量中。您可以简单地将事件处理程序附加到变量;无需分配ID,将节点注入到文档中,然后通过ID搜索。

    【讨论】:

    • 刚刚用更多背景更新了这个问题。我使用 ASP.NET MVC 来生成 html 服务器端。 ajax 调用接收 html 并将其插入到单击的行之后。
    猜你喜欢
    • 2015-07-12
    • 2019-01-18
    • 2012-02-19
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2011-07-06
    • 2010-10-11
    相关资源
    最近更新 更多