根据<template>
的内容,我想将其内容包装在容器中,以便更容易/一致地遍历。如果内容为<style>
且<one-other-element>
位于顶层,我会留下。否则,其中的任何内容都将包含在<div>
中。
最初我的代码是这样的:
var hasCtnr = template.content.querySelector(':scope > :only-child, :scope > style:first-child + :last-child') != null;
但是,我注意到它无效 - 也就是说,hasCtnr
总是false
。所以,我做了reduced test case (jsfiddle)。如您所见,:scope
适用于常规DOM元素。但是,它似乎不适用于DocumentFragment
。 我知道这项技术是新的/实验性的,但这是一个错误还是我做错了什么?
如果我使用jQuery,它可以工作......但我的猜测是因为jQuery正在手动执行某些操作。
var hasCtnr = !!$(template.content).children(':only-child, style:first-child + :last-child').length;
顺便说一句,我只关心Chrome / Electron支持。
这是jsfiddle inline:
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 });
#non-template-result {
background: red;
color: white;
}
#template-result {
background: green;
color: springgreen;
}
* /deep/ * {
margin: 10px;
padding: 5px;
}
#grandparent {
display: none;
}
<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>
答案 0 :(得分:0)
这不是错误:
:scope CSS伪类匹配作为选择器匹配的参考点的元素。在HTML中,可以使用
scoped
元素的<style>
属性定义新的参考点。 如果HTML页面上没有使用此类属性,则参考点为<html>
元素。在某些情况下,选择器可以与一组明确的
:scope
元素匹配。 这是一个(可能为空)元素集,为选择器提供与匹配的引用点,例如[DOM]中querySelector()调用指定的引用点,或者作用域的父元素[HTML5]中的<style>
元素。
由于scoped
属性为no longer on any standards track,因此只能处理带有<html>
标记的文档,这会阻止其在文档片段中使用。
根据
<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);
<template>
<style>A</style>
<one-other-element>B</one-other-element>
</template>
<template>
<picture></picture>
</template>
<强>参考强>
答案 1 :(得分:0)
声明中:
var hasCtnr = template.content.querySelector(':scope > :only-child' ) //...
... :scope
伪类表示调用querySelector()
的元素。
但是DocumentFragment(template.content
的类型)不是一个元素(没有根元素,没有容器),它的localName
属性是 undefined 。< / p>
这就是为什么这个电话永远不会选择任何东西。
var df = document.createDocumentFragment()
df.appendChild( document.createElement( 'div' ) )
var res = df.querySelector( ':scope div' )
console.info( 'df.localName is %s', df.localName )
console.info( 'df.querySelector( :scope div ) returns %s', res )
解决方法可能是将内容放在<div>
中,进行调用,然后根据结果解除或使用<div>
。