Web Components详解-Shadow DOM插槽

前言

插槽实际上也属于组件通信的一种方式,但是由于其强大的api和实用性,我将其单独拆开来介绍。

定义

Slot(插槽)是Web Components中一个重要的特性,它允许在组件内部定义占位符,以便父组件可以向其中插入内容。换句话说就是将子组件或者标签传入父组件中,最终达到在父组件外部实现子组件的效果

基本用法

slot属于Shadow DOM的一部分,在原生html中并不支持插槽的写法,所以我们必须将标签放在Shadow DOM中。

插槽标签的写法

<slot name="标签slot属性值"></slot>

需要传入的标签必须在对应的自定义标签中定义

<my-custom-element><div slot="标签slot属性值">标签</div>
</my-custom-element>

完整示例参考下面的代码

<!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>ShadowDOM</title>
</head><body><my-custom-element><header slot="header">header</header><main slot="content"><span>content</span></main><footer slot="footer">footer</footer></my-custom-element><div id="slots"><slot name="header"></slot><slot name="content"></slot><slot name="footer"></slot></div><script>const elemName = "my-custom-element"const ele = document.querySelector(elemName)const slots = document.querySelector("#slots")class MyCustomElement extends HTMLElement {constructor() {super()this.attachShadow({ mode: 'open' });this.shadowRoot.appendChild(slots)// 插槽必须在shadowDOM中}}customElements.define(elemName, MyCustomElement)</script>
</body></html>

具名插槽

具名插槽实际上就是上面的用法,在自定义标签中使用<div slot="标签slot属性值">标签</div>以及在影子DOM中使用<slot name="标签slot属性值"></slot>的形式达到效果

DOM的结构如下

匿名插槽

匿名插槽又叫默认插槽,当有slot标签不设置name属性,并且在自定义标签中存在未设置slot属性的其他标签,即具名插槽的name属性以及slot属性均未设置,此时第一个slot标签就会承载自定义标签中的全部匿名标签,参考下面的代码

<!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>ShadowDOM</title>
</head><body><my-custom-element><header>header</header><main><span>content</span></main><footer>footer</footer></my-custom-element><div id="slots"><!-- my-custom-element中的匿名标签都会放在第一个slot标签中 --><slot></slot><slot></slot><slot></slot></div><script>const elemName = "my-custom-element"const ele = document.querySelector(elemName)const slots = document.querySelector("#slots")class MyCustomElement extends HTMLElement {constructor() {super()this.attachShadow({ mode: 'open' });this.shadowRoot.appendChild(slots)}}customElements.define(elemName, MyCustomElement)</script>
</body></html>

在页面中的DOM结构如下,三个标签都被放在了第一个slot

后备插槽

当我们使用图片标签图片却加载失败时往往会给图片增加一个alt文字提醒,或使用默认图片。类似的插槽也有这种效果。当我们使用具名插槽并且找不到对应的标签时,可以在slot标签中增加标签以便默认状态展示,比如

<!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>ShadowDOM</title>
</head><body><button>显示后备插槽</button><my-custom-element><div id="content" slot="content">具名插槽</div></my-custom-element><div id="slots"><slot name="content"><div style="color: lightcoral;">后备插槽</div></slot></div><script src="./main.js"></script><script>const content = document.querySelector("#content")document.querySelector("button").addEventListener("click", () => {content.remove()// 当自定义标签my-custom-element中没有标签时,则显示后备插槽标签})</script>
</body></html>

 

当我们将自定义标签中对应的插槽删掉时,插槽元素就会显示后备插槽标签

插槽更新

当我们插入,修改,移除插槽时会触发slotchange事件钩子,类似于用于监听DOM更新的MutationObserver,来看看下面的代码

<!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>ShadowDOM</title>
</head><body><my-custom-element-change><div id="content" slot="content">插槽</div><div id="content2" slot="content2">插槽2</div></my-custom-element-change><div id="slots"><slot name="content"></slot></div><script src="./main.js"></script><script>const slot_box = `<div id="box1">slot</div>`const slot_content = slots?.querySelector('[name="content"]')slot_content.addEventListener("slotchange", console.log);customElements.define('my-custom-element-change', class extends MyCustomElement { });// 初始化触发slotchangesetTimeout(() => slot_content.name = "content2", 1000)// 替换slot绑定的元素,触发slotchangesetTimeout(() => slot_content.remove(), 2000)// 删除插槽触发slotchange</script>
</body></html>

上面的代码主要是一个简单的slotchange回调演示,创建自定义元素后,slot会初始化触发slotchange,1秒后修改slot内容触发slotchange,最后2秒后删除slot再次触发回调

插槽api

  • assignedSlot:它是标签的一个属性,通常在slot的目标标签使用,用于获取目标标签绑定的slot标签
  • assignedNodes:assignedNodes是slot上的函数,使用该方法可以返回所有分配的节点,包括文本节点和元素节点
  • assignedElements:assignedElements是slot上的函数,它会返回分配的元素节点
<!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>ShadowDOM</title>
</head><body><my-custom-element>text1<header slot="header">header</header>text2<main slot="content">content<span>content1</span><span>content2</span><span><div><span>content3</span></div></span></main><footer slot="footer">footer</footer></my-custom-element><div id="slots"><slot name="header">header</slot><slot name="content">content</slot><slot name="footer">footer</slot></div><script src="./main.js"></script><script>const elems = document.querySelectorAll('[slot]')const slotElems = slots.querySelectorAll('[name]')elems.forEach(it => console.log(it.assignedSlot))slotElems.forEach(slot => {const nodes = slot.assignedNodes();const elements = slot.assignedElements();nodes.forEach(console.log);elements.forEach(console.log);})</script>
</body></html>

总结

插槽是Web Components中的一个重要特性,用于在自定义组件内部定义占位符,使得父组件可以向其中插入内容,从而实现了组件之间的高度灵活的通信和组合。通过合理使用具名插槽、匿名插槽以及后备插槽,开发者可以实现高度定制化的组件组合。同时,插槽的事件和 API 提供了对插槽内容的监测和操作,为构建更加动态的用户界面增添了便利性。

以上就是文章全部内容了,如果觉得文章不错的话,还望三连支持一下,感谢!

相关代码

myCode: 基于js的一些小案例或者项目 - Gitee.com

参考文章

Shadow DOM 插槽,组成

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/75091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java并发】聊聊ReentrantReadWriteLock锁降级和StampedLock邮戳锁

面试题 1.你说你用过读写锁&#xff0c;锁饥饿问题是什么&#xff1f; 2.有没有比读写锁更快的锁&#xff1f; 3.StampedLock知道吗?(邮戳锁/票据锁) 4.ReentrantReadWriteLock有锁降级机制策略你知道吗&#xff1f; 在并发编程领域&#xff0c;有多线程进行提升整体性能&…

流程图 and/or/xor 讲解

and表示后续2个活动同时触发&#xff0c; or表示后续2个活动可触发其中的1个或2个&#xff0c;无排他性&#xff0c;也就是每个活动的触发不影响其他活动&#xff1b; xor表示后续2个活动只触发一个&#xff0c;有排他性&#xff0c;也就是只能触发其中一个。 示例演示“OR”…

云原生Kubernetes:Yaml文件编写

目录 一、理论 1.Kubernetes与yaml文件 二、实验 1.Kubernetes与yaml文件 三、问题 1.kubectl create 和 kubectl apply区别 四、总结 一、理论 1.Kubernetes与yaml文件 &#xff08;1&#xff09;Kubernetes支持管理资源对象的文件格式 Kubernetes支持YAML 和JSON 格…

基于微信小程序的智能垃圾分类回收系统,附源码、教程

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 1 简介 视频演示地址&#xff1a; 基于微信小程序的智能垃圾分类回收系统&#xff0c;可作为毕业设计 小…

PDF文件太大怎么办?三招教会你PDF文件压缩

PDF文件太大怎么办&#xff1f;这是许多人在处理PDF文件时遇到的问题。为了帮助大家解决这个问题&#xff0c;下面总结了三个可以解决PDF文件过大问题的方法&#xff0c;需要的朋友抓紧来看看吧~ 方法一&#xff1a;使用嗨格式压缩大师 嗨格式压缩大师是一款功能强大的PDF压缩…

无涯教程-JavaScript - IMSECH函数

描述 IMSECH函数以x yi或x yj文本格式返回复数的双曲正割。复数的双曲正割被定义为双曲余弦的倒数,即 六(z) 1/cosh(z) 语法 IMSECH (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you want the hyperbolic secant.Required Notes Ex…

手机usb连接电脑上网怎么做?掌握2个方法即可!

“我的电脑不知道怎么就连不上网络了&#xff0c;之前好像听说可以使用手机usb连接网络上网&#xff0c;但是不知道具体应该怎么操作。有没有知道详细操作步骤的朋友可以分享一下呀&#xff01;” 在需要临时共享手机网络连接或电脑无法连接Wi-Fi的情况下&#xff0c;将手机通过…

【C++基础】实现日期类

​&#x1f47b;内容专栏&#xff1a; C/C编程 &#x1f428;本文概括&#xff1a; C实现日期类。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.9.7 对于类的成员函数的声明和定义&#xff0c;我们在类和对象上讲到过&#xff0c;需要进行…

c++通过tensorRT调用模型进行推理

模型来源&#xff1a; 算法工程师训练得到的onnx模型 c对模型的转换&#xff1a; 拿到onnx模型后&#xff0c;通过tensorRT将onnx模型转换为对应的engine模型&#xff0c;注意&#xff1a;训练用的tensorRT版本和c调用的tensorRT版本必须一致。 如何转换&#xff1a; 算法工…

2020年12月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:数组指定部分逆序重放 将一个数组中的前k项按逆序重新存放。例如,将数组8,6,5,4,1前3项逆序重放得到5,6,8,4,1。 时间限制:1000 内存限制:65536 输入 输入为两行: 第一行两个整数,以空格分隔,分别为数组元素的个数n(1 < n…

在Qt5中SQLite3的使用

一、SQLite简要介绍 什么是SQLite SQLite是一个进程内的库&#xff0c;实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库&#xff0c;这意味着与其他数据库不一样&#xff0c;您不需要在系统中配置。 就像其他数据库&#xff0c;S…

基于javaweb的CT图像管理系统(servlet+jsp)

系统简介 本项目采用eclipse工具开发&#xff0c;jspservletjquery技术编写&#xff0c;数据库采用的是mysql&#xff0c;navicat开发工具。 三个角色&#xff1a;管理员&#xff0c;普通用户&#xff0c;医生 模块简介 管理员&#xff1a; 1、登录 2、用户管理 3、医生管…

ARM DIY(十)LRADC 按键

前言 ARM SOC 有别于单片机 MCU 的一点就是&#xff0c;ARM SOC 的 GPIO 比较少&#xff0c;基本上引脚都有专用的功能&#xff0c;因为它很少去接矩阵键盘、众多继电器、众多 LED。 但有时 ARM SOC 又需要三五个按键&#xff0c;这时候 LRADC 就是一个不错的选择&#xff0c;…

C# OpenVino Yolov8 Detect 目标检测

效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using static System.Net.Mime.MediaT…

python趣味编程-数独游戏

数独游戏是一个用Python编程语言编写的应用程序。该项目包含可以显示实际应用程序的基本功能。该项目可以让修读 IT 相关课程并希望开发简单应用程序的学生受益。这个Python 数独游戏是一个简单的项目,可用于学习tkinter库的实践。这个数独游戏可以提供Python编程的基本编码技…

黑马JVM总结(三)

&#xff08;1&#xff09;栈内存溢出 方法的递归调用&#xff0c;没有设置正确的结束条件&#xff0c;栈会有用完的一天&#xff0c;导致栈内存溢出 可以修改栈的大小&#xff1a; 再次运行&#xff1a;减少了次数 案例二&#xff1a; 两个类的循环应用问题&#xff0c;导致Js…

linux-进程-execl族函数

exec函数的作用&#xff1a; 我们用fork函数创建新进程后&#xff0c;经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时&#xff0c;该进程被完全替换为新程序。因为调用exec函数并不创建新进程&#xff0c;所以前后进程的ID并没有改变。 简单来说就是&…

如何使用聊天GPT自定义说明

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 OpenAI ChatGPT正在席卷全球。一周又一周&#xff0c;更新不断提高您可以使用这种最先进的语言模型做什么的标准。 在这里&#xff0c;我们深入研究了OpenAI最近在ChatGPT自定义指令上发布的公告。此功能最初以测试版…

第11篇:ESP32vscode_platformio_idf框架helloworld点亮LED

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 第3篇:vscode搭建esp32 arduino开发环境 第4篇:vscodeplatformio搭建esp32 arduino开发环境 ​​​​​​第5篇:doit_esp32_devkit_v1使用pmw呼吸灯实验 第6篇:ESP32连接无源喇叭播…

智慧公厕是对智慧城市“神经末梢”的有效激活,公共厕所实现可感知、可视化、可管理、可控制

在当今科技迅速发展的时代&#xff0c;智慧城市已经成为人们关注的热点话题。作为城市基础设施的重要组成部分&#xff0c;公共厕所也逐渐融入到智慧城市的建设中&#xff0c;成为城市管理的焦点之一。智慧公厕作为智慧城市的“神经末梢”&#xff0c;通过可感知、可视化、可管…