3

我有一个自定义组件,它只显示一张塔罗牌。在自定义元素之前,我定义了一个模板。
在我的 wc 的 connectedCallback 中,我将模板本身附加到 shadowroot,然后通过在 shadowroot 中克隆它来将其标记出来。我这样做有两个原因:

  1. 我希望我的 wc 组件是一个独立的模块;因此,我想在与自定义元素相同的位置定义我的模板。
  2. 这似乎是删除我的模板以使其可用而不将其粘贴在所有者文档中的唯一方法。

    var tmpl = `
        <template id="tmpl">
        <h1 class="tarot-title"><slot name="title">NEED TITLE</slot>
        </h1>
        <img src="${this.imageurl}" alt="">
        <p><slot name="subtitle">NEED A SUBTITLE</slot></p>
    </template>`;
    
    
    
    class BdTarot extends HTMLElement {
    
        ...constructor etc...
    
        connectedCallback() {
            this._shadowRoot.innerHTML = tmpl;
            var _tmpl = this._shadowRoot.querySelector('#tmpl');
            this._shadowRoot.appendChild(_tmpl.content.cloneNode(true));
    
        }
    
    }
    
    customElements.define('bd-tarot', BdTarot);
    

这造成的问题是我在我的页面上使用的每个塔罗牌组件都有相同的模板是一个孩子,都具有相同的 id。既然他们在shadowroot中,这有关系吗?虽然闻起来很有趣...

我的目标只是试图了解 Web 组件规范如何组合在一起。我的问题是,有没有更好的方法可以将我的组件代码保持在一起并且不参考所有者文档?由于大多数浏览器供应商没有采用 html 导入,因此模板规范是否与自定义元素大多不兼容?

4

2 回答 2

4

简而言之:如果你使用模板文字,那么你不应该使用<template>element.

您无需复制模板即可将自定义元素和模板代码保持在一起。

您可以简单地将代码包含在一个自执行函数中,以确保不会覆盖 tmpl 变量。

(function () {

var tmpl = `
    <h1 class="tarot-title"><slot name="title">NEED TITLE</slot></h1>
    <img src="${this.imageurl}" alt="">
    <p><slot name="subtitle">NEED A SUBTITLE</slot></p>`;


class BdTarot extends HTMLElement {
    constructor() {
        super()      
        this.attachShadow( { mode: 'open' } ) 
             .innerHTML = tmpl;
    }
}

customElements.define('bd-tarot', BdTarot);

})()
<bd-tarot>
<span slot="title">Queen</span>
</bd-tarot>

如果要保留模板的本地副本,可以将其复制到实例变量 ( this.tmpl) 中。

于 2017-09-07T16:01:47.097 回答
0

虽然我同意@Supersharp 的声明,即不应一起使用模板文字和模板,但我认为有更好的方法来管理组件的 HTML 模板,在您的方法之间有所混合。

本质上,与其处理字符串或模板文字,不如定义template一次并在每个组件的实例创建时从那里注入它。

const template = document.createElement('template');
template.innerHTML = `
    <h1 class="tarot-title">
        <slot name="title">NEED TITLE</slot>
    </h1>
    <img src="${this.imageurl}" alt="">
    <p>
        <slot name="subtitle">NEED A SUBTITLE</slot>
    </p>
`;

customElements.define('bd-tarot', class extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' }) 
            .appendChild(template.content.cloneNode(true));
    }
})();

我在这里写过类似的观点,还提到了我自己的库将上述大部分样板封装到几个 API 中。

于 2019-12-25T17:38:07.010 回答