假设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根)?
答案 0 :(得分:2)
我对Hayato Ito的答案采取了类似的方向。但是,我不是创建slot
元素,而是定位content
元素。我无法找到检测任何API方法检测版本的方法。
我定位了content
个元素,因为内容元素本身并没有为它们设置事件,这与slotchange
事件上的slot
不同,这有望带来小的性能提升。如果浏览器根本不支持v1
,该函数会更快地返回v0
。
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;
}
它肯定感觉像是一个“黑客”,因为需要附加随机dom :(。我在Chrome,Firefox,Safari,IE11和Edge中测试了这个。我测试了使用webcomponentsjs(v0)polyfill制作的组件,并且它为每个组件正确返回v0
。我还使用shadydom(v1)polyfill测试了那些相同的浏览器,其中包含使用v1规范创建的组件,并在所有这些浏览器中收到v1
。
答案 1 :(得分:1)
以下黑客应该有效:
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,当你必须检测到它时,会出现问题。