<template> + querySelector using:scope伪类适用于文档但不适用于documentFragment

Ols*_*dev 5 css-selectors documentfragment web-component shadow-dom html5-template

根据a的内容<template>,我想将其内容包装在容器中,以便更容易/一致地遍历.如果内容<style>,并<one-other-element>在顶层,我会离开它是.否则,那里的任何东西都会被包裹起来<div>.

最初我的代码是这样的:

var hasCtnr = template.content.querySelector(':scope > :only-child, :scope > style:first-child + :last-child') != null;
Run Code Online (Sandbox Code Playgroud)

但是,我注意到它不起作用 - 也就是说,hasCtnr总是如此false.所以,我做了一个简化的测试用例(jsfiddle).如您所见,:scope使用常规DOM元素.但是,它似乎不适用于DocumentFragments.我知道这项技术是新的/实验性的,但这是一个错误还是我做错了什么?

如果我使用jQuery,它可以工作......但我的猜测是因为jQuery手动执行某些操作.

var hasCtnr = !!$(template.content).children(':only-child, style:first-child + :last-child').length;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我只关心Chrome/Electron的支持.

这是jsfiddle内联:

var nonTmplResult = document.querySelector('#non-template-result');
var tmplResult = document.querySelector('#template-result');

var grandparent = document.querySelector('#grandparent');
var parent = document.querySelector('#parent');
var child = document.querySelector('#child');

var who = grandparent.querySelector(':scope > div');
if (who === parent) {
    nonTmplResult.innerHTML = 'parent as expected, :scope worked';
} else if (who === child) {
    nonTmplResult.innerHTML = "child (unexpected), :scope didn't work";
}


var tmpl = document.querySelector('template');
var content = tmpl.content;

var proto = Object.create(HTMLElement.prototype);

var hasCtnr = content.querySelector(':scope > div'); // this and even ':scope div' results in null, 'div' results in DIV
tmplResult.innerHTML += hasCtnr == null ? "null for some reason, :scope didn't work" : hasCtnr.nodeName + ', :scope worked'; // Why is this null..?
tmplResult.innerHTML += '<br/>';

proto.createdCallback = function() {
    var clone = document.importNode(content, true);
    var root = this.createShadowRoot();
    root.appendChild(clone);
    var rootHasCtnr = root.querySelector(':scope > div'); // ':host > div' seems to work but I prefer this check to happen once (above) so createdCallback can be efficient as I'll likely have many custom elements
    tmplResult.innerHTML += rootHasCtnr == null ? "null again, :scope didn't work" : rootHasCtnr.nodeName + ', :scope worked'; // Why is this also null..?
};

document.registerElement('x-foo', { prototype: proto });
Run Code Online (Sandbox Code Playgroud)
#non-template-result {
    background: red;
    color: white;
}
#template-result {
    background: green;
    color: springgreen;
}
* /deep/ * {
    margin: 10px;
    padding: 5px;
}
#grandparent {
    display: none;
}
Run Code Online (Sandbox Code Playgroud)
<div id="grandparent">
    <div id="parent">
        <div id="child"></div>
    </div>
</div>

<div id="non-template-result">????</div>
<div id="template-result"></div>
<x-foo>
    <p>I should be dark golden rod with khaki text.</p>
</x-foo>

<template>
    <style>
        :host {
            background: blue;
            display: block;
        }
        :host > div > p {
            color: white;
        }
        ::content > p {
            background: darkgoldenrod;
            color: khaki;
        }
    </style>
    <div>
        <p>I should be blue with white text</p>
        <content></content>
    </div>
    
</template>

<a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components#Enabling_Web_Components_in_Firefox">Enabling Web Components in Firefox</a>
Run Code Online (Sandbox Code Playgroud)

Pau*_*tte 0

这不是一个错误:

:scope CSS 伪类匹配作为选择器匹配参考点的元素。在 HTML 中,可以使用元素scoped的属性来定义新的参考点<style>如果 HTML 页面上没有使用此类属性,则参考点就是该<html>元素。

在某些上下文中,选择器可以与一组显式元素相匹配:scope这是一组(可能为空)元素,为选择器提供匹配的参考点,例如 [DOM] 中的 querySelector() 调用指定的元素,或<style>[HTML5] 中作用域元素的父元素。

由于该scoped属性不再位于任何标准轨道上,因此这只适用于带有标签的文档<html>,这将阻止其在文档片段中使用。

根据 a 的内容<template>,我想将其内容包装在容器中以便更容易/一致的遍历。如果内容是<style>顶级<one-other-element>的,我就保留它。否则,里面的任何内容都会被包裹在<div>.

var bar = document.body.getElementsByTagName("template");
var baz;

var iterator = function(value, index) {
  if(/<style>/.test(value.innerHTML) === false)
    {
    value.innerHTML = "\n<div>" + value.innerHTML + "</div>\n";
    }
  console.log(value.outerHTML);
  return value;
  };

bar.map = Array.prototype.map;
baz = bar.map(iterator);
Run Code Online (Sandbox Code Playgroud)
<template>
   <style>A</style> 
   <one-other-element>B</one-other-element> 
</template>

<template>
  <picture></picture>
</template>
Run Code Online (Sandbox Code Playgroud)

参考