有没有一种方法可以在不使用 Shadow DOM 的情况下向 <slot> 添加类似 <template> 的元素?

问题描述 投票:0回答:2

为了遵守 DRY 原则,我想创建一个基于

<template>
的自定义组件。代码看起来像这样(请原谅我在通宵达旦后在手机上打字时的偷工减料):

// 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
2个回答
3
投票

是的,

<SLOT>s
只能在shadowDOM内部使用

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

有关详细答案,请参阅:::用于shadowDOM插槽中嵌套子项的开槽CSS选择器

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>


0
投票

Danny 是对的,但还值得一提的是 外部样式表可以通过 Web 组件使用 100% 原始代码导入。您的组件可以访问该样式表的规则,对于敏锐的开发人员来说,您会很高兴知道浏览器将从其缓存中获取它,而不是发出另一个请求(假设之前已下载)。像这样:

  <!-- Component's template -->
  <template>
    <p>I'm salmon colored!</p>
    <button ord="primary">Primary button styles come from the imported stylesheet</button>
    <div class="fnt-bold">Bold class also comes from the imported stylesheet</div>

    <!-- Component's styles -->
    <style>
      /*  Importing global stylesheets will penetrate shadow DOM. Browsers use cached file if already downloaded. */
      @import "https://unpkg.com/[email protected]/dist/m-min.css";

      /* :host selects the custom element, i.e. <x-counter>, not the template. */
      :host { display: block }

      /* Anything else is scoped to this template. */
      p { color: lightsalmon }
    </style>
  </template>

完整示例:https://github.com/jfbrennan/single-file-web-component/blob/master/x-counter.html#L15

我不记得在哪里学到了有关导入的知识,但如果我能找到资源,我会更新我的答案。

© www.soinside.com 2019 - 2024. All rights reserved.