【问题标题】:Is there a way to add <slot>-like elements to a <template> without using Shadow DOM?有没有办法在不使用 Shadow DOM 的情况下向 <template> 添加类似 <slot> 的元素?
【发布时间】:2021-05-05 03:30:45
【问题描述】:

为了遵守 DRY 原则,我想创建一个基于 &lt;template&gt; 的自定义组件。代码看起来像这样(请原谅我在通宵后在手机上打字时偷工减料):

// base.html

<template id="player">
  <div class="card">
    <div class="card-body">
      <slot name="user-username"></slot>
    </div>
  </div>
</template>

// app.js

class PlayerCard extends HTMLElement {  
  constructor(){
    super();
    let tmpl = querySelector...;
    this.appendChild(tmpl.content.cloneNode();
  }
}

define('player-card', PlayerCard);

// index.html

{% for user in users %}
  <player-card>
    <div slot="user-username">{{ user }}</div>
  </player-card>
{% end for %}

但是在梦想破灭和长时间的研究之后,我了解到插槽只能在 Shadow DOM 中使用。使用 SDOM 的问题是内部样式受到保护,不能直接受到外部 CSS 的影响。

这意味着,一方面,我不能将数据注入模板实例,也不能在不重新实现 Bootstrap 的情况下使用 Shadow DOM。

我被困住了。对我的大脑来说,一定有办法让这项工作发挥作用,但我的大脑却找不到它——要么是因为它太复杂,要么是因为它太琐碎和容易。

有什么建议吗?

【问题讨论】:

    标签: javascript html web-component shadow-dom


    【解决方案1】:

    是的,&lt;SLOT&gt;s 只能在 shadowDOM 内部使用

    但您可以使用样式槽做更多事情。

    长答案见:::slotted CSS selector for nested children in shadowDOM slot

    customElements.define('player-card', class extends HTMLElement {
        constructor() {
          let template = (id) => document.getElementById(id).content.cloneNode(true);
          super()
             .attachShadow({mode: 'open'})
             .append(template(this.nodeName));
          this.onclick = (evt) => this.style.color='blue';
        }
    });
    /* GLOBAL CSS */
    player-card { /* inheritable styles trickle down into shadowDOM */
      font: 20px Arial;
      color: green;
    }
    [slot="username"] { /* lightDOM styles are REFLECTED to SLOTs */
      width: 200px;
      border: 2px solid green;
    }
    <template id="PLAYER-CARD">
      <style shadowDOM-CSS > 
        div { /* styles do not style content in SLOTs */
          padding: 1em;
          background:gold;
        }
        ::slotted(*) { /* slotted can only style the lightDOM 'skin' */
          background: lightgreen;
        }
      </style>
      <div>
        <slot name="username"></slot>
      </div>
    </template>
    
    <player-card>
        <!-- lightDOM, hidden when shadowDOM is used, then REFLECTED to SLOT -->
        <div slot="username">Ahmed</div>
    </player-card>
    
    <player-card>
        <!-- lightDOM, hidden when shadowDOM is used, then REFLECTED to SLOT -->
        <div slot="username">Danny</div>
    </player-card>

    【讨论】:

      猜你喜欢
      • 2017-10-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2023-03-27
      • 2019-08-03
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多