使用插槽和命名插槽组合自定义元素
使用Shadow DOM,我们可以创建 Web 组件,这些组件是组件内部和自定义元素用户在创作时提供的元素的组合。这与使用以下任一方法类似:选项或者选择组原生元素选择元素。这种组合是通过一种称为插槽这里我们将介绍如何在自定义元素中使用插槽和命名插槽来实现有趣的组合。
您的第一个有槽内容
允许自定义元素的用户添加自己的标记和元素作为元素的一部分,就像使用投币口组件模板中的元素。
下面是一个哑自定义元素的示例,它仅充当使用该元素时添加的内容的样式外壳:
(function() {
const template = document.createElement('template');
template.innerHTML = `
<style>
:host {
display: block;
contain: content;
text-align: center;
background: papayawhip;
max-width: 500px;
margin: 0 auto;
box-shadow: 0 0 10px rgba(128, 100, 38, 0.34);
border-radius: 8px;
border: 2px dashed #ccc049;
}
</style>
<span class="code-annotation"><slot></slot></span> `;
class MyInfoBox extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(template.content.cloneNode(true));
} }
想知道使用:主持人元素的样式需要什么?阅读有关自定义元素样式的内容。
然后可以像这样使用该元素:
<my-info-box>
<p>I'm slotted content!</p>
</my-info-box>
在自定义元素中添加的标记称为轻量级 DOM并且它处于 Shadow DOM 的范围之外,正如你从 Chrome DevTools 中看到的元素屏幕截图中所看到的那样:
轻量 DOM 中的元素可以直接作为元素的子元素进行访问,因此您可以执行如下操作来获取元素,就像通常访问 DOM 中的元素一样:
const myInfoBox = document.querySelector('my-info-box');
const text = myInfoBox.children[0].innerText;
console.log(text); // I'm slotted content!
在插槽中使用的轻量级 DOM 元素称为分布式节点。
默认内容
您可以为插槽提供默认内容,以防在使用该元素时未提供任何内容:
<slot>
<p>I'm some default content!</p>
</slot>
如果元素像这样使用,则将使用默认内容:
<my-info-box></my-info-box>
命名插槽
使用命名插槽可以轻松创建更复杂的元素,这些元素可以从元素的用户那里获取各种内容。您可以在此处看到一个简单的示例,其中命名插槽与常规插槽一起使用:
<div>
<slot name="title"></slot>
<hr>
<slot></slot>
</div>
然后可以像这样使用该元素:
<my-info-box>
<span slot="title">???? Fancy title</span>
<p>I'm going straight to the anonymous slot.</p>
</my-info-box>
借助命名插槽,您可以轻松创建将多个部分组合在一起的复杂自定义元素。例如,导航栏包含标题、徽标、左侧导航项和右侧导航项。
使用 ::slotted 为带槽内容添加样式
我们可以使用::开槽()选择器。这是一个非常简单的例子:
<style>
::slotted(span) {
background: pink;
}
::slotted(.content) {
font-family: monospace;
}
</style>
<div>
<slot name="title"></slot>
<hr>
<slot></slot>
</div>
这样,以下示例中的标题将具有粉红色背景,并且主要内容将采用等宽字体:
<my-info-box>
<span slot="title">???? Fancy title</span>
<p class="content">I'm going straight to the anonymous slot.</p>
</my-info-box>
请注意,与::开槽应该选择一个顶级元素,因为它无法匹配使用嵌套元素的插槽。