css 选择器 #(应该是)100% 相当于 jQuery 中的 [id=]?
一些背景: 我有一个网站,其中有一个显示实体列表的表格。使用 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。这会导致页面中的所有 select 元素具有相同的 id。正如有些人已经提到的,这可能就是原因。
Some background:
I have a site with a table displaying a list of entities. Using jQuery I make it possible to click on a row in the table which will load some extra data about the selected entity using AJAX. A new row is inserted into the table below the clicked row. This row contains more detailed information about the entity and is not really a row, just in HTML terms. It contains a whole bunch of data. When you click on another row, the details row currently shown will be hidden and the details row for the newly clicked entity is shown (loaded using AJAX if not loaded yet). No problems here.
On the details row there is also a select box. After loading the details row using Ajax, I want to bind the onchange event of the select. I do the following jQuery selection:
$("tr.entity_details[data-entity-id=" + entityId + "] select#SelectedDropDownValue")
The problem:
This also works fine, except in some very particular case (which I havn't been able to completely define yet). Sometimes it doesn't select the select
element. I use VS2010 to debug and entered these two items into my watch window:
$("tr.entity_details[data-entity-id=" + entityId + "] select#SelectedDropDownValue").length
$("tr.entity_details[data-entity-id=" + entityId + "] select[id=SelectedDropDownValue]").length
In the cases where the first one doesn't select anything, the second one does. This is really weird to me, because I thought that those two selectors are equivalent.
The situation when I could produce this is:
I have two entities in my table.
- I click on the bottom one first: no problem; then I click on the top one: no problem.
- I click on the top one first: no problem; then I click on the bottom one: PROBLEM.
I have no idea what could cause this. I'm thinking maybe something with me inserting new rows and hiding them in javascript, causing the selection to go a bit off. But that would be a bug I suppose. Or maybe it has something to do with that the details row contains another table and the select is in side that inner table.
EDIT:
To add some more information. I tested this under IE9 and Chrome. I am developing an ASP.NET MVC 3 application using jQuery 1.5.1. The details row is generated by a partial view. In this partial view I use the Html Helper DropDownListFor
. This helper generates the select element based on a C# property you pass to the function. It uses the property's name to generate a name and id for the element. This causes all the select elements in the page to have the same id. As some people already mentioned, that would probably be the cause.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我在一个不合规的网站上工作。我们有许多具有相同 ID 的 HTML 元素。我注意到
$('#someid')
仅抓取它找到的具有该 ID 的第一个元素,而$('[id="someid"]')
抓取具有该 ID 的所有元素。I work on a site that is, well, not compliant. We've got many HTML elements that have the same ID. I've noticed that
$('#someid')
grabs only the first element it finds with that ID while$('[id="someid"]')
grabs all elements with that ID.当遇到仅包含 ID 选择器的选择器字符串(例如
$('#my-id')
)时,jQuery 会将该 ID 直接提供给document.getElementById()
获取具有该 ID 的第一个元素,无需任何其他步骤。这是一个众所周知且有据可查的事实。如果选择器中有任何其他内容,jQuery 会完全跳过
document.getElementById()
调用。如果浏览器支持document.querySelectorAll()
并且选择器是受支持的 CSS 选择器,那么 jQuery 将使用该 API 来查询 DOM,而无需使用自己的引擎 Sizzle。否则,它会服从 Sizzle。现在,就 CSS 选择器而言,ID 选择器应该始终匹配元素 只要它由该 ID 标识,无论 HTML 是否表明在其中包含多个此类元素是无效的同一份文件。请参阅这个答案< /a> 以获得解释。我不完全确定 Sizzle 的行为是否相同,但本机实现很可能会如此。当然,由于标记必须无效才能产生影响,因此这不是您应该依赖的东西。
另一方面,像
$('[id=my-id]')
这样的属性选择器不具有与 ID 选择器相同的语义。它并不意味着“由 my-id 标识的(或任何)元素”;相反,它只是选择具有恰好名为id
且值为my-id
的属性的任何元素。因此,在 jQuery 和 CSS 中,无论文档语义如何,它总是匹配任何元素只要它具有该属性和值。也就是说,由于您正在使用 HTML,并且 HTML 表示不要识别具有相同 ID 的多个元素,因此,正如评论中提到的,当您这样做时,可能会发生未定义的行为。在这种情况下,您可能可以使用属性选择器来保证尽可能多的匹配,但我当然不建议走这条路。
When encountering a selector string containing only an ID selector, like
$('#my-id')
, jQuery feeds that ID directly todocument.getElementById()
to grab the first element with that ID, without any additional steps. This is a well-known and well-documented fact.If there's anything else in the selector at all, jQuery skips the
document.getElementById()
call entirely. If the browser supportsdocument.querySelectorAll()
and the selector is a supported CSS selector, then jQuery will use that API to query the DOM without ever using its own engine Sizzle. Otherwise, it defers to Sizzle.Now, as far as CSS selectors are concerned, an ID selector should always match element so long as it is identified by that ID, regardless of whether HTML says that it's invalid to have more than one such element in the same document. See this answer for an explanation. I am not entirely sure if Sizzle behaves the same way, but it is very likely that a native implementation would behave as such. Of course, since the markup would have to be invalid for it to make a difference, this is not something you should rely on.
An attribute selector like
$('[id=my-id]')
, on the other hand, does not carry the same semantics as an ID selector. It does not mean "the (or any) element that is identified bymy-id
"; rather, it simply selects any element with an attribute that happens to be calledid
, with the valuemy-id
. So in jQuery and CSS, and regardless of document semantics, it always matches any element so long as it has that attribute and value.That said, since you're working with HTML and HTML says not to identify multiple elements with the same ID, then as mentioned in the comments undefined behavior can occur when you do. In such a circumstance you may be able to get away with using an attribute selector which guarantees as many matches as possible, but of course I wouldn't recommend going down that route.
ID 经常被滥用。如果您使用 JavaScript 注入新的 DOM 节点,那么可能有时您会将节点放在变量中。您可以简单地将事件处理程序附加到变量;不需要分配ID,将节点注入到文档中,然后通过ID查找。
IDs are often abused. If you are injecting new DOM nodes with JavaScript, there's probably a moment when you have the node inside a variable. You can simply attach the event handler to the variable; there is no need to assign an ID, inject the node into the document and then search for it by ID.