【问题标题】:How to stamp out template in self contained custom elements with vanilla js?如何使用 vanilla js 在自包含的自定义元素中剔除模板?
【发布时间】:2018-02-16 05:38:21
【问题描述】:

我有一个自定义组件,它只显示一张塔罗牌。 在自定义元素之前,我已经定义了一个模板。
在我的 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 导入,因此模板规范是否与自定义元素大多不兼容?

【问题讨论】:

    标签: javascript dom web-component custom-element html5-template


    【解决方案1】:

    简而言之:如果您使用template literals,那么您不应该使用&lt;template&gt; 元素。

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

    您可以简单地将代码包含在一个自执行函数中,以确保不会覆盖 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)。

    【讨论】:

      【解决方案2】:

      虽然我同意 @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));
          }
      })();
      

      我在here 上写过类似的文章,还提到了我自己的库将上述大部分样板封装成几个 API。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-11
        • 2022-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多