为什么 `Selection.isCollapsed` 在影子 DOM 中总是为真?

Why is `Selection.isCollapsed` always true in a shadow DOM?

根据 MDN and javascript.info,如果当前有任何选定的文本,Selection.isCollapsed 应该是 false。对于常规 DOM,这会按预期工作,但是对于阴影 DOM,即使当前选择了某些文本,isCollapsed 似乎总是 true。有趣的是,在阴影 DOM 中调用 getSelection() 似乎确实正确地 return 当前选择——像 anchorNodeanchorOffset 这样的东西是正确的。但是 isCollapsed 总是 true,即使它应该是 false.

这是一个示例代码和框 (editor, web view),这是一个代码示例:

document.getElementById("app").innerHTML = "<h1>Hello DOM</h1>";

window.customElements.define(
  "example-component",
  class extends HTMLElement {
    constructor() {
      super();
      const mountPoint = document.createElement("div");
      this.attachShadow({ mode: "open" });
      mountPoint.innerHTML = `<h1>hello Shadow DOM</h1>`;
      this.shadowRoot?.appendChild(mountPoint);
    }
  }
);

document.addEventListener("selectionchange", () => {
  console.log("dom selectionchange");
  console.log(window.getSelection());
  console.log("shadow dom selectionchange");
  console.log(
    document.querySelector("example-component").shadowRoot.getSelection()
  );
});

我正在使用 Chrome 92.

选择 API 和阴影 dom/web 组件似乎确实存在一些问题,但正如我所说,似乎 大部分 都在工作, 只是这个 属性 不正确。

所以问题是 shadowRoot.getSelection() 不是标准的 API,并且仅在基于 Chromium 的浏览器中受支持。 document.getSelection() 不支持影子根内的选择。

正在进行扩展选择 API 以支持影子 DOM 的工作,您可以查看当前提案 in this comment 的摘要。如果该提案达成共识,shadowRoot.getSelection() API 可能会从 Chrome 中弃用,因为新的 selection.getComposedRange() API 将取而代之。

同时,此处 OP 中的行为似乎是 Chromium 中的一个错误:即使选择来自 shadowRoot.getSelection(),也会使用 document.getSelection() 中的 isCollapsed 值。我提交了 bug for this。考虑到上述工作的替代品,我不确定它会得到太多关注,但也许吧!