当前位置: 首页 > news >正文

4 html5 web components原生组件详细教程

web components 前面我们已经介绍过,这一期我们就来讲一讲具体用法和这其中的关键只是点:

1 基本使用

如果我们想实现一个封装的原生组件,那就离不开使用js去封装,这里主要就是基于HTMLElement这个类,去创建创建一个子类,然后使用customElements.define去页面中注册这个组件。

export class dialog extends HTMLElement {constructor() {super(); // 必须首先调用 super()// 正确的做法if (!this.shadowRoot) {this.attachShadow({ mode: "open" }); // 或者 'closed' 根据需求}// 创建并添加样式到影子DOM中const style = document.createElement("style");style.textContent = `dialog {padding: 0;width: 300px;height: 200px;border: 1px solid #888;}dialog::backdrop {background: rgba(0,0,0,0.5);}dialog .title {box-sizing: border-box;padding: 0 5px;width: 100%;height: 30px;line-height: 30px;color: #fff;background: var(--primary-color);}dialog .close {float: right;cursor: pointer;}dialog .footer{margin-top: 40px;}`;this.shadowRoot.appendChild(style);// 创建并添加元素到影子DOM中const div = document.createElement("div");const mode = this.getAttribute("mode") || "show";const content = this.getAttribute("content") || "我是默认内容";div.classList.add("custom-dialog");const form = `<form method="dialog">${content}<div class="footer"><button type="submit" value="submit">提交</button><button type="submit" value="cancel">取消</button></div></form>`;const dialogContent = `<dialog class="dialog"><div class="title">dialog弹窗 <span class="close">X</span></div><div class="content">${["show", "modal"].includes(mode) ? content : form}</div></dialog><button class="show-dialog">${mode}弹窗</button>`;div.innerHTML = dialogContent;this.shadowRoot.appendChild(div);this.dialog = this.shadowRoot.querySelector(".dialog");const closeEvent = (detail) =>new CustomEvent("onclose", {detail,bubbles: true, // 允许事件冒泡composed: true, // 允许事件穿透shadow DOM});this.shadowRoot.querySelector(".show-dialog").addEventListener("click", () => {if (mode === "show") {this.dialog.show();} else {this.dialog.showModal();}});this.shadowRoot.querySelector(".close").addEventListener("click", () => {this.dialog.close("top");});this.dialog.addEventListener("close", (e) => {// 触发自定义事件this.dispatchEvent(closeEvent(this.dialog.returnValue));});}
}

以上这个代码,我就封装了一个基于html5新标签dialog封装的弹窗组件,一下演示使用方法。

                <custom-dialog></custom-dialog><custom-dialogmode="modal"content="modal模式演示有close监听"></custom-dialog><custom-dialogmode="modal-form"content="modal模式演示带有表单"></custom-dialog>

以上代码我来简单分解下:

1 定义style

首先就是要给shadow Dom中要插入style标签和你自定义内容的html代码,这样来实现样式和html代码封装,主要的还是要实现代码的隔离。当然你接下来的交互,自然也要约束在你组件内部。

2 组件内查找节点

当然你js中节点事件处理,还是要基于this.shadowRoot.querySelector去做节点查找,然后使用原生的方法去做事件监听。

3 自定义事件派发:

 new CustomEvent("onclose", {detail,bubbles: true, // 允许事件冒泡composed: true, // 允许事件穿透shadow DOM});

这里就是定义一个自定义事件,然后使用this.dispatchEvent(closeEvent(this.dialog.returnValue))派发出去。

4 注册组件

接下来我们聊聊这个注册组件,以上代码仅仅是你定义组件,页面上还并不能直接使用。customElements.define(`custom-${i}`, dialog); 使用以上方法,才能在页面上以自己定义的名称使用。

2 插槽使用

插槽的使用给我们页面开发带来很大的方便,这里我们演示一下插槽的使用方法。在web components中插槽沿革执行了,组件的shadow-dom的特性,即插槽部分的样式定义和js是不受shadow-dom的this.shadowRoot的影响的,因为插槽为自定义内容,其内容被渲染也不属于组件shadow-dom内部,所以插槽被渲染出来dom结构并不在组件内部。

1 通过slot来定义插槽

<div slot="desc">纯html+css实现,无法实现更为复杂的功能和交互,而且无法实现shadow-root实现样式隔离</div>

2 使用插槽

在组件内部通过 <slot name="">来使用,如下。

const editorHtml = `<div class="editor-desc"><slot name="desc"></slot></div><div class="editor-code"><div class="code-type">${codeType}</div><div class="code-container"><div class="code-lines"></div><div class="code-content"><slot name="code"></slot></div></div></div>`;

3 插槽的渲染

其渲染出来的效果如图:

f998e35753624121b1ae9f800be7b0dd.png

这里需要特别注意插槽为自定义内容,其内容被渲染也不属于组件shadow-dom内部,所以插槽被渲染出来dom结构并不在组件内部,特别实在做样式控制时要特别注意,需要在使用组件的页面上定义样式。如果是在嵌套环境更要注意。

3 样式部分

因为shadow-dom的特性,我们样式只可以写在组件内部。但是也有一些技巧。这里我分享一个就是做样式分离的方法。

const style = document.createElement("link");style.setAttribute("rel", "stylesheet");style.setAttribute("href", "./src/assets/editor.css");this.shadowRoot.appendChild(style);

 1 分离css方法

创建一个link标签,将样式从外部链接进来,这样就可以不用做style这么麻烦了。

当然后面我再讲一讲如何做html代码分离。

样式分离了,但是这里面又有一个问题就是,样式穿透问题。这里就不得不说几个基于web component的味蕾和和选择器。

:host 这个使用在组件样式内部,表示跟组件。使用这个我们可以约束根组件的样式。通常我们封装的组件都要通过一个div元素放在根组件内部,而这个div通常我们并没有给其设置类名。这时使用这个伪类就比较好。

:host() 只选择自身包含特定选择器的自定义元素;

:host-context() 选择拥有特定选择器父元素的自定义元素。

这些选择器后面详细来讲,这里我主要谈一下,样式的从父级项向下穿透的样式规则和需求。比如我们通常定义样式有全局级别的,页面级别的,还有小组件级别的。但是现在这种shadow-dom样式的完全隔离,向实现其实比较困难。

2 样式控制

我先说第一种:页面级别,其页面级别样式可以直接影响到自己页面本身和插槽的样式,这个也很好理解。因为插槽本身就是就是小组件外的内容,样式的作用域能控制到当前页面,也就能控制当前页面内的插槽。特别是在组件嵌套的情况下,当家控制要是要特别注意。类似于这个:host/:host()都可以往出派生,都比较容易控制。

第二种情况就比较特殊了,就是全局样式。全局样式如果想穿透组件,控制组件内部,其实是比较麻烦的。这里我来详细讲一下。主要使用了::part伪元素。

.page::part(case-container) {margin: 10px 0;border: 1px solid #f6f6f6;
}
.page::part(case-title) {padding: 0 10px;line-height: 25px;font-size: 16px;
}.page::part(case-content) {background-color: #f6f6f6;padding: 10px;
}

3 样式穿透

这里大家看到,这个::part()括号中的是对应的组件.page中part属性的属性值的元素。

c68d15f1e78541c8a0d7001279f2bed6.png

如上图,这些html标签都被协商了part的key-value键值对。

前面的.page大家注意,这个地方本来是要写组件名称的,但如果写组件名称,作用域就太小了,所以我们给由相同需求的组件写一个类名,这样作用范围就更广,来实现更多需求全局样式穿透。

这个地方是给跟组件设置class的方法,建议大家在这个地方处理,这样的化,组件本身就具备了类名。但是::part不能派生,这也是个限制,希望官方后期能更新这个限制。

 this.setAttribute("class", "page");

1121b8f8cce64cb8aeaf8e9984367888.png

今天,就先分享到这,我的第一部分的原生html-web components项目部分已经马上完成,即将和大家见面。大家请关注。 

 

相关文章:

4 html5 web components原生组件详细教程

web components 前面我们已经介绍过&#xff0c;这一期我们就来讲一讲具体用法和这其中的关键只是点&#xff1a; 1 基本使用 如果我们想实现一个封装的原生组件&#xff0c;那就离不开使用js去封装&#xff0c;这里主要就是基于HTMLElement这个类&#xff0c;去创建创建一个…...

nginx+keepalived健康检查案例详解(解决nginx出现故障却不能快速切换到备份服务器的问题)

文章目录 简介配置过程前置环境请看创建健康检查脚本结果测试 简介 在我们通过nginxkeepalived实现高可用后&#xff0c;会发现nginx出现故障的时候keepalived并不会将虚拟ip切换到备份服务器上其原理就是nginx和keepalived是两个独立的服务&#xff0c;Nginx的故障状态不会触…...

什么是AI大模型?

什么是AI大模型? 人工智能&#xff08;AI&#xff09;大模型近年来在各个领域掀起了一场技术革命&#xff0c;从语言生成到图像识别&#xff0c;再到自动驾驶和医疗诊断&#xff0c;AI大模型的应用场景越来越广泛。这些模型的表现令人惊叹&#xff0c;但它们的工作原理和背后技…...

建造者模式__c#

目录 调用 指挥者 抽象建造者 建造者 定义具体产品 调用 用指挥者指挥建造者建造产品 在指挥者这里组装成产品 namespace _建造者模式 {internal class Program{static void Main(string[] args){Builder buildernew JiangHuaiBuilder();//建造者Director director new…...

学习MRI处理过程中搜到的宝藏网站

今天浏览网页查到了一些宝藏网站&#xff0c;正好记录一下&#xff0c;后面搜到好东东再接着填充&#xff0c;方便查阅~ &#xff08;1&#xff09;牛人网站 这个网站是在搜集seed关键词时发现的&#xff0c;用pdf文档记录&#xff0c;可下载查阅&#xff0c;条理清晰&#xf…...

【C语言】const char*强制类型转换 (type cast)的告警问题

void run_upload(const char *ftp_url) {CircularQueue queue;// 初始化环形队列for (int i = 0; i < QUEUE_SIZE; i++) {queue.items[i].data = malloc(BUFFER_SIZE);if (queue.items[i].data == NULL) {fprintf(stderr, "Failed to allocate memory for queue item %…...

python-比较月亮大小/数组下标/人见人爱a+b

一:比较月亮大小 题目描述 小理是一名出色的狼人。众所周知&#xff0c;狼人只有在满月之夜才会变成狼。 同时&#xff0c;月亮的大小随着时间变化&#xff0c;它的大小变化 3030 天为一循环。 它的变化情况(从第一天开始)为 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,1…...

什么是组态、组态的应用场景介绍

随着计算机技术和工业自动化水平迅速提高&#xff0c;而车间现场种类繁杂的控制设备和过程监控装置使得传统的工业控制软件无法满足用户的各种需求。在“组态”概念出现之前&#xff0c;工程技术人员需要通过编写程序来实现某一任务&#xff0c;不但工作量大、周期长&#xff0…...

Java项目: 基于SpringBoot+mybatis+maven实现的智能推荐卫生健康系统分前后台(含源码+数据库+开题报告+任务书+毕业论文)

一、项目简介 本项目是一套基于SpringBootmybatismaven实现的智能推荐卫生健康系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美…...

本地生活商城开发搭建 同城O2O线上线下推广

同城本地化商城目前如火如荼&#xff0c;不少朋友咨询本地生活同城平台怎么开发&#xff0c;今天商淘云与大家分享同城O2O线上商城的设计和开发。 本地生活商城一般会涉及到区域以及频道类&#xff0c;一般下单需要支持用户定位、商家定位&#xff0c;这样利于用户可以快速找到…...

41. 如何在MyBatis-Plus中实现批量操作?批量插入和更新的最佳实践是什么?

在 MyBatis-Plus 中&#xff0c;实现批量操作&#xff08;如批量插入、批量更新&#xff09;是非常常见的需求。MyBatis-Plus 提供了对批量操作的良好支持&#xff0c;可以通过多种方式实现高效的批量处理。下面详细介绍批量操作的实现方式以及最佳实践。 1. 批量插入 批量插入…...

LlamaIndex 的Node节点后处理器模块介绍

Node 后处理器模块 LlamaIndex 是一个旨在连接大型语言模型&#xff08;LLMs&#xff09;与外部数据的框架&#xff0c;允许开发者构建能够处理和回应复杂查询的应用程序。在这个框架内&#xff0c;NodePostProcessor 扮演着优化数据处理流程的重要角色。为了更好地理解 NodeP…...

Dubbo 如何使用 Zookeeper 作为注册中心:原理、优势与实现详解

Dubbo 是一个高性能的 Java 分布式服务框架&#xff0c;而 Zookeeper 常被用作 Dubbo 的服务注册中心。Zookeeper 提供了分布式一致性和协调服务&#xff0c;Dubbo 通过 Zookeeper 实现服务注册与发现功能&#xff0c;确保在分布式环境下服务实例的动态管理和可靠发现。 下面是…...

Linux:进程间通信之命名管道

Linux&#xff1a;进程间通信-CSDN博客 我们说匿名管道只能用于父子进程这样的关系通信&#xff0c;那么陌生进程怎么通信&#xff1f; 我们之前说父子进程能通信的最关键的地方就在于子进程复制了一份父进程的files_struct&#xff0c;从而通过文件的inode映射同一份文件来通…...

UE4_后期处理七—仿红外线成像效果

效果图展示&#xff1a; 参考文档&#xff1a;https://dev.epicgames.com/documentation/zh-cn/unreal-engine/using-fresnel-in-your-unreal-engine-materials?application_version5.4 二、所用知识点扩充 在创建电影或过场动画时&#xff0c;你常常需要想办法更好地突显角…...

静态路由和默认路由(实验)

目录 一、实验设备和环境 1、实验设备 2、实验环境 &#xff08;1&#xff09;实验拓扑图 &#xff08;2&#xff09;实验命令列表 二、实验记录 1、直连路由与路由表查看 步骤1:建立物理连接并运行超级终端。 步骤2:在路由器上查看路由表。 2、静态路由配置 步骤1:配…...

TCP: Textual-based Class-aware Prompt tuning for Visual-Language Model

文章汇总 存在的问题 原文&#xff1a;具有图像特定知识的图像条件提示符号在提升类嵌入分布方面的能力较差。 个人理解&#xff1a;单纯把"a photo of {class}"这种提示模版作为输入是不利于text encoder学习的 动机 在可学习的提示和每一类的文本知识之间建立…...

2024年软考网络工程师中级题库

1【考生回忆版】以下不属于5G网络优点的是&#xff08;A) A.传输过程中消耗的资源少&#xff0c;对设备的电池更友好 B.支持大规模物联网&#xff0c;能够连接大量低功耗设备&#xff0c;提供更高效的管理 C.引入了网络切片技术&#xff0c;允许将物理网络划分为多个虚拟网络…...

CSS的盒子模型(Box Model)

所有HTML元素都可以看作盒子&#xff0c;在CSS中盒子模型是用来设计和布局的&#xff0c;CSS盒子模型本质上是一个盒子&#xff0c;分装周围的HTML元素包括&#xff1a;外边距&#xff0c;边框&#xff0c;内边距和实际内容。 Margin&#xff08;外边距&#xff09; 清除边框…...

用OpenSSL搭建PKI证书体系

1 创建PKI结构目录 mkdir 07_PKI cd 07_PKI mkdir 01_RootCA 02_SubCA 03_Client2 创建根CA cd 01_RootCA mkdir key csr cert newcerts touch index.txt index.txt.attr echo 01 > serial2.1 创建根CA密钥对 2.1.1 生成 长度为2048 bit 的RSA私钥。 cd key openssl gen…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...