如何定义一个像<img>
那样的Web组件,因为它不接受任何子元素?
<script>
const QA = (q, d) => Array.prototype.slice.call((d||document).querySelectorAll(q), 0);
const QS = (q, d) => (d||document).querySelector(q);
</script>
<template id="push-message">
<style>
message { display: grid; font-family: sans-serif; background: #eee; outline: 1px solid; }
.badge { }
</style>
<message>
<img class="badge">
<img class="icon">
<img class="image">
</message>
</template>
<script>
const wpm = 'push-message';
customElements.define(wpm,
class extends HTMLElement {
constructor() {
super();
const l = QS(`#${wpm}`).content.cloneNode(true);
const s = this.attachShadow({ mode: 'open' }); s.appendChild(l);
}
QS(q) { return QS(q, this.shadowRoot); }
QA(q) { return QA(q, this.shadowRoot); }
static get observedAttributes() { return [ "badge", "icon", "image" ]; }
attributeChangedCallback(a, o, n) {
if (/^(badge|icon|image)$/.test(a))
this.QS(`.${a}`).src = n;
}
});
</script>
<push-message
badge="//google.com/favicon.ico"
icon="//google.com/favicon.ico"
image="//google.com/favicon.ico">
<p>ok</p>
DOM
应该是
<push-message></push-message>
<p></p>
不是
<push-message><p></p></push-message>
和ok
应该显示在结果中。
是否有一种方法可以更改customElements.define
来避免必须显式关闭<push-message></push-message>
而只使用<push-message>
却隐式地自动关闭?
答案 0 :(得分:3)
自治的自定义元素需要一个结束标记:Do custom elements require a close tag?
您可以创建从HTMLImageElement扩展的自定义内置元素
以获得自动关闭的IMG标签:
<img is="push-message" badge="//google.com/favicon.ico">
<img is="push-message" icon="//google.com/favicon.ico">
<img is="push-message" image="//google.com/favicon.ico">
<p>ok</p>
但是IMG只能有一个src,因此您最好创建3个元素并使用
<img is="message-badge">
<img is="message-icon">
<img is="message-image">
答案 1 :(得分:2)
自动关闭标签,称为void elements。
AFAIK,无法创建自定义的空元素。总而言之,它需要更改浏览器HTML解析器,这对于Web社区而言并非易事。由于浏览器实现tag-soup algorithm的方式,因此需要进行更改。
因此,您将需要一个结束标记。您可以在此处阅读有关此内容的更多信息:
另一方面,如果您有自己的模板编译器/解析器,例如vue-compiler
和ng-compiler
,则可以指示它在构建时了解自动关闭的自定义元素。但是,实现此目标的好处几乎不存在。