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 插槽的渲染
其渲染出来的效果如图:
这里需要特别注意插槽为自定义内容,其内容被渲染也不属于组件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属性的属性值的元素。
如上图,这些html标签都被协商了part的key-value键值对。
前面的.page大家注意,这个地方本来是要写组件名称的,但如果写组件名称,作用域就太小了,所以我们给由相同需求的组件写一个类名,这样作用范围就更广,来实现更多需求全局样式穿透。
这个地方是给跟组件设置class的方法,建议大家在这个地方处理,这样的化,组件本身就具备了类名。但是::part不能派生,这也是个限制,希望官方后期能更新这个限制。
this.setAttribute("class", "page");
今天,就先分享到这,我的第一部分的原生html-web components项目部分已经马上完成,即将和大家见面。大家请关注。
相关文章:

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

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

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

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

学习MRI处理过程中搜到的宝藏网站
今天浏览网页查到了一些宝藏网站,正好记录一下,后面搜到好东东再接着填充,方便查阅~ (1)牛人网站 这个网站是在搜集seed关键词时发现的,用pdf文档记录,可下载查阅,条理清晰…...

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

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

Java项目: 基于SpringBoot+mybatis+maven实现的智能推荐卫生健康系统分前后台(含源码+数据库+开题报告+任务书+毕业论文)
一、项目简介 本项目是一套基于SpringBootmybatismaven实现的智能推荐卫生健康系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美…...

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

41. 如何在MyBatis-Plus中实现批量操作?批量插入和更新的最佳实践是什么?
在 MyBatis-Plus 中,实现批量操作(如批量插入、批量更新)是非常常见的需求。MyBatis-Plus 提供了对批量操作的良好支持,可以通过多种方式实现高效的批量处理。下面详细介绍批量操作的实现方式以及最佳实践。 1. 批量插入 批量插入…...

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

Dubbo 如何使用 Zookeeper 作为注册中心:原理、优势与实现详解
Dubbo 是一个高性能的 Java 分布式服务框架,而 Zookeeper 常被用作 Dubbo 的服务注册中心。Zookeeper 提供了分布式一致性和协调服务,Dubbo 通过 Zookeeper 实现服务注册与发现功能,确保在分布式环境下服务实例的动态管理和可靠发现。 下面是…...

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

UE4_后期处理七—仿红外线成像效果
效果图展示: 参考文档:https://dev.epicgames.com/documentation/zh-cn/unreal-engine/using-fresnel-in-your-unreal-engine-materials?application_version5.4 二、所用知识点扩充 在创建电影或过场动画时,你常常需要想办法更好地突显角…...

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

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

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

CSS的盒子模型(Box Model)
所有HTML元素都可以看作盒子,在CSS中盒子模型是用来设计和布局的,CSS盒子模型本质上是一个盒子,分装周围的HTML元素包括:外边距,边框,内边距和实际内容。 Margin(外边距) 清除边框…...

用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…...

scp 命令:在两台主机间远程传输文件
一、命令简介 scp 命令使用 SSH 加密的方式在本地主机和远程主机之间复制文件。 二、命令参数 格式 scp [选项] 发送方主机和目录 接收方主机和目录注意:左边是发送方,右边是接收方。固定格式。 示例 #示例1 scp ~/test.txt soulio172.1…...

家用迷你洗衣机哪款质量高?五大热销高分单品强势来袭
迷你内衣洗衣机一般是为婴儿宝宝,或者一些有特殊需要的用户而设计使用的,宝宝衣物换洗频繁,而且对卫生方面的除菌要求高,而为避免交叉感染,所以一般不适合和大人的衣物放在一起洗,因此对于有宝宝的家庭来说…...

rpm 命令:RedHat底层包管理器
一、命令简介 rpm 是 Red Hat Package Manager 的缩写,是 Red Hat、CentOS、Fedora 等基于 Red Hat 的 Linux 发行版中用于管理和安装软件包的工具。它能够安装、卸载、升级、查询和验证软件包。 相关命令: rpm 是基础,提供了底层的软…...

Xilinx 使用DDS实现本振混频上下变频
文章目录 一、什么是混频?二、为什么要进行混频?三、Matlab实现混频操作四、FPGA实现混频上下变频操作4.1 例化IP4.2 仿真验证 一、什么是混频? 混频(Mixing)是信号处理中的一个核心概念,混频的本质是将两个…...

ClickHouse-Kafka Engine 正确的使用方式
Kafka 是大数据领域非常流行的一款分布式消息中间件,是实时计算中必不可少的一环,同时一款 OLAP 系统能否对接 Kafka 也算是考量是否具备流批一体的衡量指标之一。ClickHouse 的 Kafka 表引擎能够直接与 Kafka 系统对接,进而订阅 Kafka 中的 …...

PTA L1-071 前世档案
L1-071 前世档案(20分) 网络世界中时常会遇到这类滑稽的算命小程序,实现原理很简单,随便设计几个问题,根据玩家对每个问题的回答选择一条判断树中的路径(如下图所示),结论就是路径终…...

解决mac下 Android Studio gradle 下载很慢,如何手动配置
抓住人生中的一分一秒,胜过虚度中的一月一年! 小做个动图开篇引题 前言 平时我们clone git 上项目,项目对应gradle版本本地没有,ide编译会自动下载,但是超级慢可能还下载失败,下面讲解下此问题如 如下图所示ÿ…...

第三篇 第17章 工程计量与支付
第三篇 工程计价 第17章 工程计量与支付 17.1 工程计量 17.1.1 工程计量的原则 承包人完成合同工程且应予计量的工程数量确定计量周期可以月为单位,也可以按其他时间节点、工程形象进度分段计量因承包人原因造成的超出合同工程范围施工或返工的工程量、发包人不予计量 17.1…...

[半导体检测-1]:半导体检测概述
前言: 半导体检测是半导体产业链中不可或缺的一环,它贯穿于产品生产制造流程的始终,对于提高产线良率、提升产品竞争实力具有关键作用。以下是对半导体检测的详细概述: 一、什么是半导体检测 半导体检测是指运用专业技术手段&a…...

公共字段自动填充
问题分析 总会有些公共字段,例如创建时间和创建人 实现思路 对mapper定义注解,使用切面思想来判断是不是更新和新增操作对于指定的操作来更新公共字段 自定义操作类型 package com.sky.enumeration;/*** 数据库操作类型*/ public enum OperationType {/*…...