我们如何检测影子根是用 v0 还是 v1 API 创建的?
How do we detect if a shadow root was made with v0 or v1 API?
假设一个 JS 模块导出 shadowRoot
,它是使用 el.createShadowRoot
或 el.attachShadow
(我们不知道是哪个)创建的。我们如何检测根是 v0 影子根还是 v1 影子根(即我们如何检测使用哪种方法创建根)?
f.e.,下面的条件语句填什么?
// for argument's sake, we don't create the root, we only get a reference
// to it:
import shadowRoot from 'somewhere'
function getShadowRootVersion(root) {
if ( ... )
return 'v0'
if ( ... )
return 'v1'
}
console.log(getShadowRootVersion(shadowRoot)) // should output "v0" or "v1".
更多信息:
我们想知道影子根是从 createShadowRoot
还是从 attachShadow
创建的。生成的根是不同的:在用 createShadowRoot
创建的根中, <content>
元素用于分配元素。在使用 attachShadow
创建的根中,<content>
元素不执行任何操作,而是使用 <slot>
元素。我们如何检测使用哪种方法创建根(即我们是否有 v0 根或 v1 根)?
以下 hack 应该有效:
function isV1(shadowRoot) {
const slot = document.createElement('slot');
shadowRoot.appendChild(slot);
slot.appendChild(document.createElement('div'));
const assignedNodes = slot.assignedNodes({ flatten: true });
slot.remove();
return assignedNodes.length !== 0;
}
IMO,一定要检测的时候出问题了
我的方向与伊藤隼人的回答相似。但是,我没有创建 slot
个元素,而是以 content
个元素为目标。我无法找到一种方法来检测任何 API 方法检测的版本。
我以 content
元素为目标,因为内容元素本身没有事件,这与 slot
事件上的 slotchange
不同,后者有望带来小幅性能提升。如果浏览器根本不支持 v0
,加上函数 returns v1
会快一点。
function shadowType(shadowRoot) {
if (!shadowRoot) {
// closed shadow dom does not appear to have a shadowRoot...
// It could be assumed that it is v1, but for now return undefined
return;
}
const content = document.createElement('content');
// In browsers that support v1, but not v0 (ex: Safari)
if (!content.getDistributedNodes) {
return 'v1';
}
content.setAttribute('select', 'test-shadow-dom-version');
shadowRoot.appendChild(content);
const testElement = document.createElement('test-shadow-dom-version');
shadowRoot.host.appendChild(testElement);
const type = (content.getDistributedNodes().length) ? 'v0' : 'v1';
shadowRoot.removeChild(content);
shadowRoot.host.removeChild(testElement);
return type;
}
感觉确实像 "hack",因为需要附加 运行dom dom :(。我在 Chrome 中测试过这个, Firefox、Safari、IE11 和 Edge。我测试了使用 webcomponentsjs (v0) polyfill 制作的组件,它为每个组件正确返回了 v0
。我还测试了那些相同的浏览器,仅使用 shadydom ( v1) 使用 v1 规范创建的组件进行 polyfill,并在所有这些浏览器中收到 v1
。
假设一个 JS 模块导出 shadowRoot
,它是使用 el.createShadowRoot
或 el.attachShadow
(我们不知道是哪个)创建的。我们如何检测根是 v0 影子根还是 v1 影子根(即我们如何检测使用哪种方法创建根)?
f.e.,下面的条件语句填什么?
// for argument's sake, we don't create the root, we only get a reference
// to it:
import shadowRoot from 'somewhere'
function getShadowRootVersion(root) {
if ( ... )
return 'v0'
if ( ... )
return 'v1'
}
console.log(getShadowRootVersion(shadowRoot)) // should output "v0" or "v1".
更多信息:
我们想知道影子根是从 createShadowRoot
还是从 attachShadow
创建的。生成的根是不同的:在用 createShadowRoot
创建的根中, <content>
元素用于分配元素。在使用 attachShadow
创建的根中,<content>
元素不执行任何操作,而是使用 <slot>
元素。我们如何检测使用哪种方法创建根(即我们是否有 v0 根或 v1 根)?
以下 hack 应该有效:
function isV1(shadowRoot) {
const slot = document.createElement('slot');
shadowRoot.appendChild(slot);
slot.appendChild(document.createElement('div'));
const assignedNodes = slot.assignedNodes({ flatten: true });
slot.remove();
return assignedNodes.length !== 0;
}
IMO,一定要检测的时候出问题了
我的方向与伊藤隼人的回答相似。但是,我没有创建 slot
个元素,而是以 content
个元素为目标。我无法找到一种方法来检测任何 API 方法检测的版本。
我以 content
元素为目标,因为内容元素本身没有事件,这与 slot
事件上的 slotchange
不同,后者有望带来小幅性能提升。如果浏览器根本不支持 v0
,加上函数 returns v1
会快一点。
function shadowType(shadowRoot) {
if (!shadowRoot) {
// closed shadow dom does not appear to have a shadowRoot...
// It could be assumed that it is v1, but for now return undefined
return;
}
const content = document.createElement('content');
// In browsers that support v1, but not v0 (ex: Safari)
if (!content.getDistributedNodes) {
return 'v1';
}
content.setAttribute('select', 'test-shadow-dom-version');
shadowRoot.appendChild(content);
const testElement = document.createElement('test-shadow-dom-version');
shadowRoot.host.appendChild(testElement);
const type = (content.getDistributedNodes().length) ? 'v0' : 'v1';
shadowRoot.removeChild(content);
shadowRoot.host.removeChild(testElement);
return type;
}
感觉确实像 "hack",因为需要附加 运行dom dom :(。我在 Chrome 中测试过这个, Firefox、Safari、IE11 和 Edge。我测试了使用 webcomponentsjs (v0) polyfill 制作的组件,它为每个组件正确返回了 v0
。我还测试了那些相同的浏览器,仅使用 shadydom ( v1) 使用 v1 规范创建的组件进行 polyfill,并在所有这些浏览器中收到 v1
。