slot全局属性 <slot>标签</slot> ::slotted()伪元素 笔记240223

252 阅读8分钟

slot全局属性 标签 ::slotted()伪元素

MDN HTML全局属性

MDN HTML全局属性 slot

MDN HTML <slot>标签元素

MDN CSS ::slotted()为元素

MDN 使用 templates and slots

<slot>标签

<slot>标签是的 displaycontents




在Web开发中,<slot>元素和::slotted()伪元素都与Web组件(特别是Shadow DOM)有关。这些功能允许开发者创建可复用的自定义元素,这些元素可以像任何其他HTML元素一样使用,但具有封装的内部结构和样式。

  1. <slot> 元素:

<slot>元素用于在自定义元素的Shadow DOM中定义插槽,这些插槽允许主DOM(即自定义元素的常规HTML内容)中的元素被渲染到Shadow DOM中的特定位置。插槽可以具有名称(通过name属性指定)或无名称(默认插槽)。

例如,在自定义元素的Shadow DOM中,您可能有以下内容:

<div class="card">
  <slot name="header"></slot>
  <div class="content">
    <slot></slot> <!-- 默认插槽 -->
  </div>
  <slot name="footer"></slot>
</div>

在主DOM中,您可以这样使用这个自定义元素:

<my-custom-element>
  <h2 slot="header">标题</h2>
  <p>这是一些内容。</p> <!-- 这将进入默认插槽 -->
  <div slot="footer">页脚信息</div>
</my-custom-element>
  1. ::slotted() 伪元素:

::slotted()伪元素允许您从Shadow DOM内部选择并样式化插槽内容。换句话说,它让您能够影响那些通过插槽传递进来的元素的样式。这在您希望保持Shadow DOM的封装性,同时又需要某种程度地控制插槽内容的样式时非常有用。

例如,如果您想更改通过默认插槽传递进来的文本的颜色,您可以在自定义元素的样式表中这样做:

::slotted(*) {
  color: blue; /* 这将影响所有插槽的内容 */
}

/* 或者更具体地针对默认插槽 */
::slotted(:not([slot])) {
  color: blue; /* 这将只影响默认插槽的内容 */
}

请注意,::slotted()的样式只会应用到插槽的直接子元素上。如果需要影响更深层次的子元素,您可能需要在主DOM中提供额外的样式或结构。

总的来说,<slot>::slotted()提供了强大的工具来创建可复用、可定制且封装良好的Web组件。




在您提供的代码片段中,<slot slot="slot"></slot> 似乎是一个尝试使用 <slot> 元素的示例,但它实际上是不正确的。在 HTML 和 Web 组件的上下文中,<slot> 元素通常不会带有 slot 属性,除非是在某些特定的框架或库中有特别的规定。标准的用法是,<slot> 元素可以有一个 name 属性来指定插槽的名称,如 <slot name="header"></slot>

然而,如果您在开发环境中遇到 <slot slot="slot"></slot> 这样的代码,并且它按预期工作,那么这可能是因为您正在使用的框架或库对 <slot> 元素进行了自定义处理。但在原生 Web 组件和标准的 Shadow DOM 中,这样的用法是不常见的,也可能是错误的。

至于 ::slotted(),正如我之前解释的那样,它是一个 CSS 伪元素,用于从 Shadow DOM 内部选择并应用样式到插槽的内容。但是,它应该与具体的选择器一起使用,而不是单独出现。例如:

::slotted(p) {
  color: red; /* 这将把通过任何插槽传递进来的 <p> 元素的文本颜色设置为红色 */
}

或者,如果您想针对具有特定 slot 属性的插槽内容应用样式(尽管这不是标准用法),您可能需要在主 DOM 中使用普通的 CSS 选择器,因为 ::slotted() 本身不支持基于 slot 属性的选择。例如:

/* 这不会工作,因为 ::slotted() 不支持属性选择器来匹配插槽的名称 */
::slotted([slot="slot"]) {
  color: red; /* 这将不会应用,因为选择器不正确 */
}

实际上,如果您想根据插槽的 name 属性应用样式,您应该在主 DOM 中为插槽内容指定类名或直接使用元素选择器,并在 Shadow DOM 中使用相应的 ::slotted() 选择器来匹配这些类名或元素。但是,请记住,::slotted() 只能影响插槽的直接子元素。

如果您确实看到了 <slot slot="slot"></slot> 这样的代码,并且它在您的项目中有效,我建议您查阅您正在使用的框架或库的文档,以了解这是否是该环境的特定语法或行为。在标准的 Web 组件和 Shadow DOM 中,这样的用法通常是不正确的。




在Web组件的上下文中,slot 既可以作为一个全局属性(用于分配内容到指定的插槽),也可以作为 <slot> 元素(用于在Shadow DOM中定义插槽)。而 ::slotted() 是一个CSS伪元素,用于从Shadow DOM内部选择并样式化插槽的内容。

首先,让我们澄清一下 slot 作为全局属性的用法。通常,您不会直接将 slot 属性应用于 <slot> 标签本身。相反,slot 属性是应用于自定义元素的子元素,以指示这些子元素应该被分配到哪个插槽。

例如,如果您有一个自定义元素 <my-card>,它在其Shadow DOM中定义了几个插槽:

<!-- my-card的Shadow DOM结构 -->
<div class="card">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot> <!-- 默认插槽 -->
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

当您在常规HTML中使用 <my-card> 时,您可以通过 slot 属性将内容分配到这些插槽中:

<my-card>
  <h1 slot="header">Welcome to My Card</h1>
  <p>This is some default content.</p> <!-- 这将进入默认插槽 -->
  <p slot="footer">©2023 My Company</p>
</my-card>

在这里,slot="header"slot="footer" 是全局属性,它们告诉浏览器将这些元素分配到 <my-card> 的相应插槽中。没有指定 slot 属性的元素默认会进入无名(默认)插槽。

接下来是 <slot> 元素。如上所示,<slot> 元素在自定义元素的Shadow DOM中定义了一个插槽,它可以接收来自主DOM的内容。插槽可以是命名的(通过 name 属性)或默认的(没有 name 属性)。

最后,::slotted() 伪元素允许您从Shadow DOM内部选择并应用样式到通过插槽传递进来的内容。例如:

/* 在my-card的Shadow DOM样式表中 */
::slotted(h1) {
  color: blue; /* 这将把通过名为"header"的插槽传递进来的<h1>元素的文本颜色设置为蓝色 */
}

::slotted(p) {
  color: gray; /* 这将影响所有通过插槽传递进来的<p>元素,除非它们的样式被更具体地覆盖 */
}

请注意,::slotted() 只能影响直接插入到插槽中的元素。如果您需要影响更深层次的子元素,您可能需要在主DOM中提供额外的样式或结构,或者使用其他CSS组合器来增加选择器的特异性。




HTML <slot> 标签是 Web 组件技术中的一部分,特别是与 Shadow DOM 一起使用时。<slot> 元素在自定义元素的 Shadow DOM 中创建了一个占位符,该占位符可以由使用该自定义元素的主 DOM 中的内容填充。

以下是使用 HTML <slot> 标签的基本步骤:

  1. 创建自定义元素:首先,您需要定义一个自定义元素,这通常是通过使用 JavaScript 和 class 关键字扩展 HTMLElement 来完成的。

  2. 附加 Shadow DOM:为您的自定义元素附加一个 Shadow DOM。Shadow DOM 允许您将封装的结构、样式和行为与主 DOM 分离。

  3. 在 Shadow DOM 中使用 <slot>:在 Shadow DOM 的模板中,使用 <slot> 标签来定义插槽。您可以为 <slot> 元素指定一个 name 属性,以便能够将特定的内容分配给特定的插槽。

  4. 在主 DOM 中使用自定义元素:在主 DOM 中,像使用任何其他 HTML 元素一样使用您的自定义元素。要填充插槽,请将内容放在自定义元素的开始和结束标签之间,并使用 slot 属性指定要插入内容的插槽名称(如果插槽有名称的话)。

下面是一个简单的例子:

自定义元素定义

<!-- 假设这是在一个 JavaScript 文件中 -->
<script>
class MyCustomElement extends HTMLElement {
  constructor() {
    super(); // 必须首先调用 super()

    // 创建一个 shadow root
    const shadow = this.attachShadow({ mode: 'open' });

    // 创建一个插槽
    const slot = document.createElement('slot');
    slot.setAttribute('name', 'my-slot'); // 可以选择给插槽命名

    // 将插槽附加到 shadow DOM
    shadow.appendChild(slot);
  }
}

// 定义自定义元素
customElements.define('my-custom-element', MyCustomElement);
</script>

在 HTML 中使用自定义元素

<!-- 在 HTML 文件中使用这个自定义元素 -->
<my-custom-element>
  <p slot="my-slot">这段内容将被插入到名为 "my-slot" 的插槽中。</p>
  <!-- 如果没有指定 slot 属性,或者 slot 属性值与任何插槽不匹配,则内容不会被插入到 Shadow DOM 中 -->
</my-custom-element>

然而,在实际情况中,您通常会在 Shadow DOM 的模板中使用 <slot>,而不是通过 JavaScript 动态创建它。这可以通过使用 <template> 元素和 innerHTML 来实现,如下所示:

<script>
class MyCustomElement extends HTMLElement {
  constructor() {
    super(); // 必须首先调用 super()

    // 创建一个 shadow root
    const shadow = this.attachShadow({ mode: 'open' });

    // 创建一个模板并添加到 shadow DOM
    const template = document.createElement('template');
    template.innerHTML = `
      <div>Some internal structure</div>
      <slot name="my-slot"></slot> <!-- 在模板中定义插槽 -->
    `;
    const node = document.importNode(template.content, true);
    shadow.appendChild(node);
  }
}

customElements.define('my-custom-element', MyCustomElement);
</script>

在这个例子中,<slot name="my-slot"></slot> 是在模板字符串中定义的,然后整个模板内容被导入到 Shadow DOM 中。这种方法更常见,因为它允许您以更声明式的方式定义自定义元素的内部结构。