有什么办法可以将自定义元素的模板标记和样式保留在javascript字符串之外? [英] Any way to keep a custom elemnt's template markup and style outside of a javascript string?

查看:52
本文介绍了有什么办法可以将自定义元素的模板标记和样式保留在javascript字符串之外?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是使用来自 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆