是否允许在单独的影子根中使用重复的 ID?

Posted

技术标签:

【中文标题】是否允许在单独的影子根中使用重复的 ID?【英文标题】:Are duplicate IDs allowed in separate shadow roots? 【发布时间】:2019-09-25 03:49:10 【问题描述】:

tl;博士:

    两个元素具有相同的 ID 属性是否有效,只要它们位于不同的影子根下? 屏幕阅读器会在这种情况下正确处理aria-labelledby吗?

例如,考虑这个自定义元素:

(function () 
  let template = document.createElement('template')
  template.innerhtml = `
    <svg viewBox="0 0 206 74"
         fill="none"
         xmlns="http://www.w3.org/2000/svg"
         role="img"
         aria-labelledby="logo-title">
      <title id="logo-title"><slot>Logo of Some Company.</slot></title>

      <path d="..." fill="..."/>
    </svg>
  `

  class Logo extends HTMLElement 
    constructor () 
      super()

      let shadowRoot = this.attachShadow(mode: 'open')
      shadowRoot.appendChild(template.content.cloneNode(true))
    
  

  customElements.define('company-logo', Logo)
)()

这样做是否有效:

<company-logo>
  Title One.
</company-logo>

<company-logo>
  Some other title.
</company-logo>

这是否是一个有效的 DOM,即使 &lt;title&gt; 共享相同的 ID?屏幕阅读器是否会为第一个徽标读取“Title One”,而为第二个徽标读取“Some other title”?

【问题讨论】:

我不确定,但我的猜测是否定的。 ID 的点是唯一标识符。如果您想通过 ID 选择其中之一,您如何知道目标是哪一个? @ChrisBarr querySelectorgetElementById 不要跨越阴影根边界,所以这应该不是问题,不是吗? 我想不是,但为什么还要有相同的 ID 呢?似乎至少让开发人员感到困惑已经成熟了。为什么不让ID带有随机后缀?喜欢id="logo-title-$Math.random().toString(36).substr(2, 8)" 我只是想知道它是否合法并且处理得当。在规范中找不到任何明确提及此案例的内容。 好吧,我也不知道,但是使用真正唯一的 ID 不会有什么坏处。此外,您可以尝试使用屏幕阅读器,看看它是否有效 - 下载 ChromeVox 扩展程序,它非常易于使用。 【参考方案1】:

您可以在同一页面上拥有相同自定义元素的多个实例,因此内部 Shadow DOM 将通过设计共享相同的 ID。

就标准而言...

W3C's HTML5 Rec 不包括 Shadow DOM,因此它不是他们的主题。

WHATWG's HTML Living Standard 声明 ID 在节点树中应该是唯一的,但如果涉及扁平化树(Light DOM 树和 Shadow DOM 树的组合),则并不精确。据我了解,规格并没有说它无效:-)

在 HTML 元素上指定时,id 属性值在元素树中的所有 ID 中必须是唯一的,并且必须包含至少一个字符。

实际上,浏览器处理相同的 ID 不是问题。

我不认为 Aria 标签可以跨 Shadow DOM,它应该取决于浏览器的实现。再次在 Shadow DOM 上 the specs says nothing。


2019 年更新

正如谷歌在 Shadow DOM 的介绍中所述:

Scoped DOM 意味着您可以使用简单的 CSS 选择器、更通用的 id/类名称,而不必担心命名冲突。

事实上,Shadow DOM 允许您创建可以分发和重用的 Web 组件,内部 ID 与同一页面中其他组件的其他 ID 匹配但由其他开发人员开发的可能性很高,而 Scoped DOM 是一个好答案。


2020 年更新

请注意,Shadow DOM / ARIA 问题仍然是being discussed。

未来 AOM(可访问性对象模型)将以编程方式允许 to solve this kind of question。

您不仅可以通过id 标签链接元素,还可以通过引用链接元素:

element.ariaLabelledByElements = [ anotherElement, someOtherElement ]

无需处理 ID 的唯一性,以及跨越 Shadow DOM 边界的可能性 :-) 也许有一天 :-(

【讨论】:

浏览器不强制 ID 唯一性是有原因的。所有供应商都实施了微软很久以前开始的 ID 行为。文档是一回事。实践是另一回事。如果你知道你在做什么,重复 ID 可以很强大 请注意,行为只在全局范围内...... ShadowDOM 内的重复不会创建 NodeList,单个 ID 也不会创建具有相同名称的变量。供应商不太可能禁用这种全球行为,因为它会破坏财富 500 强公司的大量(糟糕)网站。但是阅读开发人员阅读手册总是很有趣。 @Danny'365CSI'Engelman 其实我忘了一句话:我想写“浏览器处理相同的 ID 不是问题” 影子mode: 'open' 仍然如此吗? @connexo 你说的这个是什么意思?【参考方案2】:

我认为拥有 Shadow DOM 的具体原因之一是您可以拥有多个具有相同格式和结构的项目。这包括 ID 和类。每个 Shadow DOM 就像它自己的小文档。这对程序员来说有很大的优势,因为他们可以多次重复 Shadow 元素,而无需为 Shadow 中的元素生成唯一 ID。

【讨论】:

以上是关于是否允许在单独的影子根中使用重复的 ID?的主要内容,如果未能解决你的问题,请参考以下文章

rails模型的影子表

MySQL - 在单独的列中跟踪重复记录类型

使用实体框架从聚合根中删除子记录

为啥 HTML 中不允许重复的 ID 值?

阴影 dom 内的聚合物元素有效,但没有样式

如何使用jquery知道是不是存在具有特定ID的div [重复]