有什么办法可以将自定义元素的模板标记和样式保留在javascript字符串之外? [英] Any way to keep a custom elemnt's template markup and style outside of a javascript string?
问题描述
这是使用来自 developers.google的自定义元素的示例.com :
let tmpl = document.createElement('template');
tmpl.innerHTML = `
<style>:host { ... }</style> <!-- look ma, scoped styles -->
<b>I'm in shadow dom!</b>
<slot></slot>
`;
customElements.define('x-foo-shadowdom', class extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// Attach a shadow root to the element.
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(tmpl.content.cloneNode(true));
}
...
});
虽然这行得通,但我发现这种方法很难看.HTML和CSS应该驻留在.html和.css文件中,而不是作为Javascript字符串.
While this works I find this approach oddly ugly. HTML and CSS should reside in .html and .css files, not as Javascript strings.
同时我不知道如何将这些内容移动到.html或.css文件?
At the same time I don’t know how to move this content to .html or .css files?
是的,我可以使用可能会使用的所有自定义元素的< template>
标签填充主HTML文件(即 index.html
).这不会破坏自定义元素的目的吗?
Well yes I could populate the main HTML file, namely index.html
, with <template>
tags for all custom elements that may be ever used – but doesn't this defeat the purpose of custom elements?
< link rel ="import">
可能很有希望,但已删除.
还有其他选择吗?
(或者我不正确地发现原来的解决方案很丑吗?)
(Or am I incorrect to find the original solution ugly?)
推荐答案
您可以使用 fetch()
获取自定义元素内容的HTML文件.
You could use fetch()
to get an HTML file for your Custom Element content.
customElements.define('x-foo-shadowdom', class extends HTMLElement {
constructor() {
super()
this.attachShadow( {mode: 'open'} )
}
async connectedCallback() {
let res = await fetch( 'x-foo.html' )
this.shadowRoot.innerHTML = await res.text()
}
}
NB:由于 fetch()
和 text()
是异步的,因此必须在 connectedCallback()
之前添加 async
.方法调用之前,code>和 await
.
NB: because fetch()
and text()
are asynchronous, you must add async
before connectedCallback()
and await
before the method calls.
您还可以简单地通过使用HTML代码中的< link>
获得单独的CSS内容.
You can also get separate CSS content simply by using <link>
in the HTML code.
我很难找到原始的解决方案吗?
am I incorrect to find the original solution ugly?
是的,很丑.如果要使用模板文字,则无需将其放在< template>
元素中并进行克隆.
Yes it's ugly.
If you want to use a template literal then no need to put it in a <template>
element and clone it.
相反,请直接使用模板文字:
Instead, use the template literal directly:
shadowRoot.innerHTML = `
<style>:host { ... }</style> <!-- look ma, scoped styles -->
<b>I'm in shadow dom!</b>
<slot></slot>
`;
请注意,模板文字与单独的HTML相比有一个优势:您可以轻松使用插入变量.带有增量clic计数器的示例:
Note that there's an advantage with template literals vs separate HTML: you can use insert variables easily. Example with an incremental clic counter:
customElements.define( 'click-counter', class extends HTMLElement {
connectedCallback() {
let count = 0
let sh = this.attachShadow( { mode: 'open' } )
this.onclick = () => sh.innerHTML = `<button>${count++}</button>`
this.click()
}
} )
<click-counter></click-counter>
这篇关于有什么办法可以将自定义元素的模板标记和样式保留在javascript字符串之外?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!