持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
- 使用Slot可以在单个实例中通过声明式的语法展示不同的文本
- 没有template元素也是可以使用slot的
- 能被插入到插槽内的元素称之为Slotable,已经被插入到插槽内的元素称之为Slotted
具名插槽
<slot>元素内可以添加默认结构,当不存在对应名称从带有slot属性的元素时,会显示该结构。
<template id="slot-test">
<p>
<slot name="slotable-test">
这里是默认文字,当该该插槽没有被使用时,插槽位置显示默认结构
</slot>
</p>
</template>
- 同一个名称的
<slot>可以插入多个结构,也就是说,多个元素的slot元素为同名时,会被依次插入<slot>的位置
<slot-test>
<div slot="slotable-test">
这里是使用插槽后的元素,带有slot的元素会被插入对应插槽
</div>
<div slot="slotable-test">
同一个名字的插槽可以插入多个带有slot的元素
</div>
</slot-test>
- 只能在顶层子元素中使用slot元素,非顶层子元素使用slot属性会被忽略,如下面代码所示,在div中嵌套的div带有slot属性,但并不会被插入到对应位置。
<slot-test>
<div>
<div slot="slotable-test">
仅仅顶层子元素可以设置slot,其他子元素设置会被忽略,该段文字在非顶层子元素,不会显示
</div>
</div>
</slot-test>
- 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<template id="slot-test">
<p><slot name="slotable-test">这里是默认文字,当该该插槽没有被使用时,插槽位置显示默认结构</slot></p>
</template>
<slot-test>
<div class="slot" slot="slotable-test">这里是使用插槽后的元素,带有slot的元素会被插入对应插槽</div>
<div class="slot" slot="slotable-test">同一个名字的插槽可以插入多个带有slot的元素</div>
<div>
<div class="slot" slot="slotable-test">仅仅顶层元素可以设置slot,子元素设置会被忽略,该段文字在子元素,不会显示</div>
</div>
</slot-test>
</body>
<script>
customElements.define('slot-test',
class extends HTMLElement {
constructor() {
super();
let template = document.getElementById('slot-test');
let templateContent = template.content;
const shadowRoot = this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
}
})
</script>
</html>
- 从下图我们可以看到渲染结果,可以看到带有slot属性的元素的结构并未被真实的插入到对应位置,而是在对应位置创建了一个映射。那么CSS和JavaScript的行为又是怎么样的呢
- 使用JavaScript选择器
let num1 = document.querySelectorAll("slot-test .slot").length
console.log(num1) //3
let num2 = document.querySelectorAll("p .slot").length
console.log(num2) //0
- 使用CSS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.slot{
color: red;
}
</style>
<body>
<template id="slot-test">
<style>
.slot{
color: blue;
}
p{
color: brown;
}
</style>
<p><slot name="slotable-test">这里是默认文字,当该该插槽没有被使用时,插槽位置显示默认结构</slot></p>
</template>
<slot-test>
<div class="slot" slot="slotable-test">这里是使用插槽后的元素,带有slot的元素会被插入对应插槽</div>
<div class="slot" slot="slotable-test">同一个名字的插槽可以插入多个带有slot的元素</div>
<div>
<div class="slot" slot="slotable-test">仅仅顶层元素可以设置slot,子元素设置会被忽略,该段文字在子元素,不会显示</div>
</div>
</slot-test>
</body>
<script>
customElements.define('slot-test',
class extends HTMLElement {
constructor() {
super();
let template = document.getElementById('slot-test');
let templateContent = template.content;
const shadowRoot = this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
}
})
</script>
</html>
可以看到,文字的颜色为红色,仅仅在渲染结构的改变了,由于在文档内节点仍然没有改变,外层的CSS渲染和JS控制仍然是可以控制的,且在shadow dom内无法使用.slot的className进行样式渲染,生效的属性为light tree中的style样式。