【发布时间】:2020-10-19 18:33:14
【问题描述】:
我正在使用标准自定义元素和自闭合自定义元素。
当声明彼此紧邻时,它们并没有像我预期的那样完全工作。
如果我编写两个彼此紧邻的标准自定义元素:
<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra"></colour-list>
它们都正常显示:
const schemes = {
rainbowJSON : '["red", "orange", "yellow", "green", "blue", "indigo", "violet"]',
zebraJSON : '["black", "white", "black", "white", "black"]'
}
class colourList_CustomElement extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: "open"});
}
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
display: inline-block; /* <= Because Custom elements are display:inline by default */
contain: content; /* <= Because this delivers an immediate performance win */
}
ul {
margin: 0 24px 0 0;
padding: 0;
width: 200px;
list-style-type: none;
}
li {
height: 24px;
text-align: center;
font-weight: bold;
text-shadow: 1px 1px rgba(0, 0, 0, 0.7);
}
</style>
`;
let schemeJSON = schemes[this.getAttribute('scheme') + 'JSON'];
let colours = JSON.parse(schemeJSON);
let colourList = document.createElement('ul');
let listItem;
for (let colour of colours) {
listItem = document.createElement('li');
let textShadow = (colour === 'black') ? 'text-shadow: 1px 1px rgba(255, 255, 255, 0.7);' : '';
listItem.setAttribute('style', 'color: '+ colour + '; background-color: ' + colour + ';' + textShadow);
listItem.textContent = colour;
colourList.appendChild(listItem);
}
this.root.appendChild(colourList);
}
}
customElements.define('colour-list', colourList_CustomElement);
<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra"></colour-list>
或者,如果我有一个紧跟标准自定义元素的自闭合自定义元素:
<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra" />
它们也都正常显示:
const schemes = {
rainbowJSON : '["red", "orange", "yellow", "green", "blue", "indigo", "violet"]',
zebraJSON : '["black", "white", "black", "white", "black"]'
}
class colourList_CustomElement extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: "open"});
}
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
display: inline-block; /* <= Because Custom elements are display:inline by default */
contain: content; /* <= Because this delivers an immediate performance win */
}
ul {
margin: 0 24px 0 0;
padding: 0;
width: 200px;
list-style-type: none;
}
li {
height: 24px;
text-align: center;
font-weight: bold;
text-shadow: 1px 1px rgba(0, 0, 0, 0.7);
}
</style>
`;
let schemeJSON = schemes[this.getAttribute('scheme') + 'JSON'];
let colours = JSON.parse(schemeJSON);
let colourList = document.createElement('ul');
let listItem;
for (let colour of colours) {
listItem = document.createElement('li');
let textShadow = (colour === 'black') ? 'text-shadow: 1px 1px rgba(255, 255, 255, 0.7);' : '';
listItem.setAttribute('style', 'color: '+ colour + '; background-color: ' + colour + ';' + textShadow);
listItem.textContent = colour;
colourList.appendChild(listItem);
}
this.root.appendChild(colourList);
}
}
customElements.define('colour-list', colourList_CustomElement);
<colour-list scheme="rainbow"></colour-list>
<colour-list scheme="zebra" />
但是,最后,如果我有两个自闭合元素,一个紧跟在前一个之后,第二个自定义元素根本不会显示:
<colour-list scheme="rainbow" />
<colour-list scheme="zebra" />
const schemes = {
rainbowJSON : '["red", "orange", "yellow", "green", "blue", "indigo", "violet"]',
zebraJSON : '["black", "white", "black", "white", "black"]'
}
class colourList_CustomElement extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: "open"});
}
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
display: inline-block; /* <= Because Custom elements are display:inline by default */
contain: content; /* <= Because this delivers an immediate performance win */
}
ul {
margin: 0 24px 0 0;
padding: 0;
width: 200px;
list-style-type: none;
}
li {
height: 24px;
text-align: center;
font-weight: bold;
text-shadow: 1px 1px rgba(0, 0, 0, 0.7);
}
</style>
`;
let schemeJSON = schemes[this.getAttribute('scheme') + 'JSON'];
let colours = JSON.parse(schemeJSON);
let colourList = document.createElement('ul');
let listItem;
for (let colour of colours) {
listItem = document.createElement('li');
let textShadow = (colour === 'black') ? 'text-shadow: 1px 1px rgba(255, 255, 255, 0.7);' : '';
listItem.setAttribute('style', 'color: '+ colour + '; background-color: ' + colour + ';' + textShadow);
listItem.textContent = colour;
colourList.appendChild(listItem);
}
this.root.appendChild(colourList);
}
}
customElements.define('colour-list', colourList_CustomElement);
<colour-list scheme="rainbow" />
<colour-list scheme="zebra" />
我不清楚为什么在最后一个示例中两个元素都没有显示。
【问题讨论】:
-
自治自定义元素不能自动关闭。只有定制的内置元素(如 IMG)可以......但 Apple 拒绝实现定制的内置元素。
-
给你:github.com/w3c/webcomponents/issues/624 rniwa 是 Apple,annevk 是 Mozilla,hayatoito 是 Google
-
没有自定义的自动关闭元素。自闭合(无效)元素是precisely defined exceptions to the normal parsing algorithm,用于
img、br、meta、input和其他一些元素。始终明确关闭您的元素。你得到的是两个缺少结束标签的嵌套元素。 -
这是一个很棒的链接@Danny'365CSI'Engelman - 非常感谢。我分享了该线程中许多参与者对自动关闭自定义元素的热情。我也明白为什么 void 自定义元素很难解析,但肯定不是自关闭自定义元素(?)自关闭自定义元素的正则表达式是:
^\<[a-z][\-]*\-[\-]*\s?\/\>$。
标签: javascript html custom-element