Web 原生组件化方案:Web Components

你好,我是沐爸,欢迎点赞、收藏、评论和关注。

Web 组件化是一种将Web应用的UI部分拆分成可复用的独立组件的架构方法。这种方法有助于提高代码的可维护性、可重用性和可测试性。
而Web Components 标准则提供了一套原生的API,允许开发者创建可复用的自定义元素,这些元素封装了HTML、CSS和JavaScript,并且可以在任何现代浏览器中作为标准的HTML元素来使用。

Web Components 标准主要包括以下几个部分:

  1. Custom Elements(自定义元素):允许开发者定义自己的HTML元素。
  2. Shadow DOM(影子DOM):为元素提供了一个封装的DOM和样式作用域,使得元素内部的样式和行为不会影响到外部,反之亦然。
  3. HTML Templates(HTML模板)<template>标签允许开发者定义一段不会立即渲染的HTML内容,可以稍后通过JavaScript来实例化并插入到文档中。
  4. Slots(插槽):虽然不是Web Components标准的一部分,但经常与Shadow DOM一起使用,用于在父组件中指定子组件内容插入的位置。

下面通过3个示例,对 Web Components 的用法进行展示。

示例1:Hello World 组件

以下是一个简单的Web组件示例,它创建了一个自定义的<hello-world>元素,该元素在屏幕上显示“Hello, World!”:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Web Components Example</title>
</head>
<body>
    <hello-world></hello-world>

    <script>
        // 自定义元素类
        class HelloWorld extends HTMLElement {
            constructor() {
                super()
                // 创建一个影子DOM
                const shadow = this.attachShadow({ mode: 'open' })

                // 定义并插入HTML模板
                shadow.innerHTML = `
                    <style>
                        p { color: blue; }
                    </style>
                    <p>Hello, World!</p>
                `
            }
        }

        // 注册自定义元素
        customElements.define('hello-world', HelloWorld)
    </script>
</body>
</html>

在这个例子中,我们首先定义了一个名为HelloWorld的类,它继承自HTMLElement。在constructor方法中,我们调用super()来调用父类的构造函数,并创建了一个影子DOM。然后,我们通过设置shadow.innerHTML来定义元素的内部结构和样式。最后,我们使用customElements.define方法来注册这个自定义元素,使其可以在HTML文档中使用。

在HTML文档中,我们通过<hello-world></hello-world>标签来使用这个自定义元素。当浏览器解析到这个标签时,它会创建一个HelloWorld类的实例,并将其插入到DOM中。由于我们使用了影子DOM,所以<hello-world>元素内部的样式和结构不会影响到外部的其他元素,也不会被外部样式所影响。

审查元素看下自定义元素长什么样:

示例2: 简单的计数器组件

以下示例创建了一个自定义元素,它显示一个计数器,用户可以通过点击按钮来增加计数。

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>Counter Web Component</title>  
</head>  
<body>  
    <counter-element></counter-element>  
  
    <script>  
        class CounterElement extends HTMLElement {  
            constructor() {  
                super();  
                this.count = 0;  
  
                // 创建影子DOM  
                const shadow = this.attachShadow({ mode: 'open' });  
  
                // 样式  
                shadow.innerHTML = `  
                    <style>  
                        button { margin: 5px; }  
                    </style>  
                    <p>Count: <span>${this.count}</span></p>  
                    <button οnclick="this.parentNode.host.increment()">Increment</button>  
                `;  
  
                // 获取元素引用  
                this.countDisplay = shadow.querySelector('span');  
            }  
  
            increment() {  
                this.count++;  
                this.countDisplay.textContent = this.count;  
            }  
  
            // 静态getter,允许外部访问increment方法  
            static get observedAttributes() {  
                return []; // 本例不观察属性变化  
            }  
  
            connectedCallback() {  
                // 元素被添加到DOM时执行  
                // 可以在这里添加事件监听器等  
            }  
  
            disconnectedCallback() {  
                // 元素从DOM中移除时执行  
                // 可以在这里移除事件监听器等  
            }  
        }  
  
        // 注册自定义元素  
        customElements.define('counter-element', CounterElement);  
    </script>  
</body>  
</html>

注意:在上面的示例中,我直接在按钮的onclick属性中使用了this.parentNode.host.increment(),这虽然可以工作,但通常不是最佳实践。更好的做法是使用addEventListener来添加事件监听器,并在回调函数中调用increment方法。然而,为了保持示例的简洁性,我选择了这种方式。

示例3:插槽(Slots)

下面的示例创建了一个 <custom-card> 元素,它使用slot 元素来允许用户插入自定义内容。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Custom Card Web Component</title>
    <style>
        /* 全局样式,不会影响组件样式 */
        .card-content {
            padding: 10px;
            border: 1px solid red;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <custom-card>
        <h2 slot="header">Card Title</h2>
        <p>This is the content of the card.</p>
    </custom-card>

    <script>
        class CustomCard extends HTMLElement {
            constructor() {
                super()

                // 创建影子DOM
                const shadow = this.attachShadow({ mode: 'open' })

                // 样式和HTML结构
                shadow.innerHTML = `
                    <style>
                        :host {
                            display: block;
                            margin: 20px;
                        }
                        .header {
                            background-color: #f0f0f0;
                            padding: 5px;
                            text-align: center;
                        }
                        .card-content {
                            padding: 20px;
                        }
                    </style>
                    <div class="header">
                        <slot name="header"></slot>
                    </div>
                    <div class="card-content">
                        <slot></slot>
                    </div>
                `
            }
        }

        // 注册自定义元素
        customElements.define('custom-card', CustomCard)
    </script>
</body>
</html>

在这个示例中,<custom-card>元素包含了一个带有header插槽的头部和一个默认的插槽用于内容。在HTML中,我们通过指定 slot 属性来将内容分配到相应的插槽中。

好了,分享结束,谢谢点赞,下期再见。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA 通义灵码 插件使用体验

目录 前言 主要功能 演示代码 解释代码 生成单元测试 生成代码注释 生成优化建议 代码片段补全 总结 前言 自从 AI 技术开始大规模应用&#xff0c;老板就想让下面的牛马借助 AI 工具来提高编码效率&#xff0c;由于团队都没有在实际编码中深度使用过 AI 工具&#x…

视频推拉流/直播点播EasyDSS平台安装失败并报错“install mediaserver error”是什么原因?

TSINGSEE青犀视频推拉流/直播点播EasyDSS平台支持音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务&#xff0c;在应用场景中可实现视频直播、点播、转码、管理、录像、检索、时移回看等。此外&#xff0c;平台还支持用户自行上传视频文件&#xff0c;也可…

【物联网技术大作业】设计一个智能家居的应用场景

前言&#xff1a; 本人的物联网技术的期末大作业&#xff0c;希望对你有帮助。 目录 大作业设计题 &#xff08;1&#xff09;智能家居的概述。 &#xff08;2&#xff09;介绍智能家居应用。要求至少5个方面的应用&#xff0c;包括每个应用所采用的设备&#xff0c;性能&am…

【深度学习】神经网络-怎么分清DNN、CNN、RNN?

怎么分清DNN、CNN、RNN&#xff1f; 最“大”的概念是人工神经网络&#xff08;Artificial Neural Network, ANN&#xff09;&#xff0c;它是较为广泛的术语&#xff0c;通常指的是一类模拟生物神经网络的数学模型&#xff0c;其中包括神经元、权重和连接。在这个术语下&#…

【Redis】主从复制 - 源码

因为主从复制的过程很复杂, 同时核心逻辑主要集中在 replication.c 这个文件中, 避免篇幅过大, 所以将主从复制中涉及这个文件的代码集中到了另一篇文章。 在当前文章主要分析主从复制的大体代码逻辑, 如果需要了解整体的过程, 可以配合 Redis 主从复制 - relication 源码分析 …

iOS 知识点记录

王巍 博客地址&#xff1a;OneVs Den git地址&#xff1a;onevcat (Wei Wang) GitHub 江湖人称喵神&#xff0c;目前就职于line。喵神的博客涉及方面比较广, 有Obejctive-C, Swift, SwiftUI, Unity等等。博客内容很有深度&#xff0c;非常值得关注。 戴铭 博客地址&#xff1…

ESP32-WROOM-32 开篇(刚买)

简介 买了一个ESP32-WROOM-32模块的开发板, 记录板初上机细节。 模块简介 Look 连接PC 1. 解决驱动问题 https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tabdownloads 下载驱动, 如下图 解压缩下载的包&#xff0c; 然后电机64位的版本&#xff0c; 一直…

汽车无钥匙启动功能工作原理

移‌动管家无钥匙启动‌是一种科技化的汽车启动方式&#xff0c;它允许车主在不使用传统钥匙的情况下启动车辆。这种技术通过智能感应系统实现&#xff0c;车主只需携带智能钥匙&#xff0c;当靠近车辆时&#xff0c;车辆能够自动解锁并准备启动。启动车辆时&#xff0c;车主无…

友思特方案 | 搭建红外桥梁:嵌入式视觉接口助力红外热像仪传输

导读 为红外成像设备数据传输快速搭桥&#xff01;友思特嵌入式视觉接口能帮助用户快速享有 GigE Vision 协议优势&#xff0c;是红外成像设备视觉接口集成、开发高性能相机的高效快捷方案。 引言 红外热像仪作为一种非接触式设备&#xff0c;能够检测红外能量&#xff08;热量…

CSS实现前端布局更巧妙的方案!在 flex 布局中通过使用 margin 实现水平垂直居中以及其他常见的前端布局

在前端开发中&#xff0c;实现水平垂直居中一直是个热门话题。随着 CSS Flexbox 布局的普及&#xff0c;开发者们开始更多地使用 justify-content 和 align-items 这两个属性来解决这个问题。 然而&#xff0c;还有一种更加简洁、灵活的方式——使用 margin: auto; 来实现居中以…

Grafana面板-linux主机详情(使用标签过滤主机监控)

1. 采集器添加labels标签区分业务项目 targets添加labels &#xff08;模板中使用的project标签&#xff09; … targets: [‘xxxx:9100’] labels: project: app2targets: [‘xxxx:9100’] labels: project: app1 … 2. grafana面板套用 21902 模板 演示

UE5 阴影通道

Shadow Pass Switch节点中 Default代表模型遮罩的效果 Shadow代表阴影的生成遮罩效果

3. 进阶指南:自定义 Prompt 提升大模型解题能力

怎么判断 Prompt 的好坏&#xff0c;有什么问题有着标准答案么&#xff1f; 答&#xff1a;让大模型求解数学问题。 李宏毅老师的 HW4 正好提到了有关数学问题的 Prompt&#xff0c;所以我决定中间插一篇这样的文章。通过本文你将&#xff1a; 了解各种 Prompt 如何影响大型语言…

从C语言过渡到C++

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;C &#x1f3c5;往期回顾&#x1f3c6;&#xff1a;单链表实现&#xff1a;从理论到代码-CSDN博客&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱的博客-CSDN博客 目录 ​…

HOT 100(七)栈、堆、贪心算法

一、栈 1、每日温度 使用单调递减栈来解决。主要思路是遍历temperatures数组&#xff0c;利用栈来存储还没有找到比当前温度高的天数的索引。当遇到比栈顶索引所对应温度更高的温度时&#xff0c;就可以确定当前这一天的温度比之前那一天高。索引的差值就是等待的天数。 求一…

Golang数据流处理:掌握Reader和Writer接口的技巧

Golang数据流处理&#xff1a;掌握Reader和Writer接口的技巧 引言理解Reader和Writer接口Reader接口的定义和基本方法Writer接口的定义和基本方法 Reader接口的深入探讨Reader接口的实现示例使用io.Reader读取文件内容从网络连接中读取数据 常用Reader类型及其应用场景strings.…

相图的科学应用,陶瓷材料创新

陶瓷材料因其优异的物理和化学性能&#xff0c;在航空航天、电子、生物医学等多个领域展现出广阔的应用前景。陶瓷材料的性能很大程度上取决于其微观结构&#xff0c;包括晶粒大小、相组成和分布。相图作为描述陶瓷材料在不同条件下的相变行为和相平衡关系的图表反映了陶瓷材料…

10年Python程序员教你多平台采集10万+电商数据【附实例】

10万级电商数据采集需要注意什么&#xff1f; 在进行10万级电商数据采集时&#xff0c;有许多关键因素需要注意&#xff1a; 1. 采集平台覆盖&#xff1a;确保可以覆盖主流的电商平台&#xff0c;如淘宝、天猫、京东、拼多多等。 2. 数据字段覆盖&#xff1a;检查是否可以对平…

什么是VHDX文件?

VHDX文件是Docker环境中使用的一种虚拟硬盘文件格式&#xff0c;专门用于存储Docker容器 的镜像和数据。这种文件格式&#xff0c;VHDX&#xff0c;代表Virtual Hard Disk Extended&#xff0c;是一种用于虚拟化环境的硬盘文件格式&#xff0c;支持动态扩展、快照、加密等功能&…

python基础知识 (五)--容器、索引、切片、字符串的遍历、查找、修改元素

目录 容器 容器大总结 索引 切片 字符串的遍历 for循环语法&#xff1a; while循环语法&#xff1a; 查找元素 修改元素 例题 1.验证码 2.抽取大红包 3.a和b互换位置 容器 在Python中&#xff0c;常见容器有&#xff1a; &#xff08;1&#xff09;字符串&#x…