关于Web Component

2024年8月14日

引言

Web Component 是一种用于构建可复用用户界面组件的技术,开发者可以创建自定义的 HTML 标签,并将其封装为包含逻辑和样式的独立组件,从而在任何 Web 应用中重复使用,并且可以做到无框架跨框架。

不同于 Vue/React 等社区或厂商的组件化开发方案,Web Component 被定义在标准的 HTML 和 DOM 标准中。它由一组相关的 Web 平台 API 组成,也可以与现有的前端框架和库配合使用Web Component 的兼容性良好,可以在现代浏览器中直接使用,也可以通过 polyfill 兼容到旧版浏览器。

每个 Web Component 都具有自己的 DOM 和样式隔离,避免了全局 CSS 和 JavaScript 的冲突问题。它还支持自定义事件和属性,可以与其他组件进行通信和交互。实现这些主要基于其三个技术:

  • Custom elements:一组JavaScript API,允许您定义custom elements及其行为,然后可以在您的用户界面中按照需要使用它们。
  • Shadow DOM:一组JavaScript API,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突
  • HTML templates:<template> 和 <slot> 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。

如何简单创建一个Web Components

挂载

首先为这个项目创建一个文件夹,然后在里面为组件准备一个button.js文件,在这里将编写一个按钮组件,button.js文件内容如下:

  1. 模版
let templateTemp = `
<template id='button'><div class="button">按钮</div>
</template>
`;
  1. 样式
let styleTemp = `
.button{width:70px;height:50px;background-color:rgb(54, 54, 252);color: white;display: flex;justify-content: center;align-items: center;border-radius: 10px;user-select: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;cursor: pointer;
}
.button:hover{background-color:rgb(38, 38, 250);
}
.button:active{background-color:rgb(5, 5, 255);
}`;
  1. 将模版字符串转化为document节点
const parser = new DOMParser();
const doc = parser.parseFromString(templateTemp, "text/html");
const temp = doc.getElementById("button");
  1. 创建自定义组件
class button extends HTMLElement {constructor() {super();//创建一个影子节点,组件会挂载在上面,参数mode表示是否可被外部访问const shadow = this.attachShadow({ mode: "open" });//获取模版和样式const content = temp.content.cloneNode(true);const style = document.createElement("style");style.textContent = styleTemp;//挂载shadow.appendChild(style);shadow.append(content);}
}
customElements.define("zf-button", button);
  1. 接下来查看这个组件,比如在一个原生的index.html文件中
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><link rel="icon" type="svg+xml" href="public/logo.svg"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>My HTML File</title><link rel="stylesheet" type="text/css" href="style.css"><script src="script.js"></script>//导入文件<script src="button.js"></script>
</head>
<body>//直接使用模版<zf-button></zf-button>
</body>
</html>

这样一个简单的Web Component就挂载好了并且可以看到了。
在这里插入图片描述
现在这个按钮已经有最基本的样式,但相比Element组件库的按钮还不够丰富,比如按钮的类型,或大或小的,在用这个组件时可以以参数的方式进行切换,还有颜色等等,这些就涉及如何与组件通讯了,还有想让按钮有个图标,这样就要用到插槽。在处理这些问题前,先来了解Web Component的生命周期。


生命周期

一个Web Component有4个生命周期

  1. connectedCallback
    首次插入文档DOM时调用,这个回调函数通常用于执行一些初始化操作,比如添加事件监听器、请求数据等等。在这个时候,元素已经被添加到了文档中,可以访问到this.shadowRoot里的 DOM 和其他元素。
  2. disconnectedCallback
    从文档删除时调用,这个回调函数通常用于清理一些资源,比如取消事件监听器、停止定时器等等。在这个时候,元素已经不再被文档所包含,无法访问到 DOM 和其他元素。
  3. adoptedCallback
    移动到新文档时调用,这个回调函数通常用于处理一些文档级别的操作,比如重新计算布局(重排)、修改样式等等。在这个时候,元素已经从原来的文档中移除,并被添加到了新的文档中。
  4. attributeChangedCallback
    修改自身属性时调用,这个回调函数通常用于处理一些属性相关的逻辑,比如根据属性值的变化更新元素的样式、重新渲染元素等等。在这个时候,元素的属性已经被修改,可以通过新的属性值来进行相应的处理。
class button extends HTMLElement {constructor() {super();}connectedCallback() {console.log("首次插入文档");}disconnectedCallback() {console.log("从文档删除");}adoptedCallback() {console.log("移动到新文档");}attributeChangedCallback() {console.log("修改");}
}

组件通讯

组件通讯主要就是外部传递信息给组件内部和组件内部传递信息给外部。主要的实现在于shadowRoot的方法去操作组件的自定义属性。比如想要修改刚才按钮组件的文字,那么给组件添加自定义属性text:

<zf-button text="添加"></zf-button>

然后在生命周期connectedCallback中获取并赋值

connectedCallback() {if (this.hasAttribute("text")) {this.shadowRoot.querySelector(".button").innerHTML =this.getAttribute("text");}
}

再或者想要点击这个按钮后,文字变为修改,这个就得在生命周期attributeChangedCallback去监听text属性,如果有huan hu。
首先要添加observedAttributes数组,元素为自定义属性的名字,这样attributeChangedCallback才能监听。

static observedAttributes = ["text"];

接着在attributeChangedCallback,监听到text的变化,然后在shadowRoot中找到按钮组件进行修改。

attributeChangedCallback(name, oldValue, newValue) {if (name === "text") {this.shadowRoot.querySelector(".button").innerHTML =newValue;}
}

最后就是外部如何去修改组件的自定义属性,这里需要shadow节点可以被访问

const shadow = this.attachShadow({ mode: "open" });

然后给组件添加点击事件,在里面修改组件的属性值,这样的修改会被组件的attributeChangedCallback函数捕抓。

document.addEventListener("DOMContentLoaded", function () {document.querySelector("#btn").addEventListener("click", function () {document.querySelector("#btn").attributes.text.value = "修改";});
});

用Web Component构建组件库

这样的组件库相比针对Vue的element和针对react的vant,它不会受框架的限制,就是不能享受语言框架带来的便利。比如Vue的响应式属性和事件绑定,在原生的html不具备,然后其组件库也是不能使用的,只能用原生的方法去实现。这样的组件库我找到了:

Quark Design
https://quark-ecosystem.github.io/quarkd-docs/vue/#/

还有一些框架可以自己去搭建Web Component组件库,比如Omi框架,在这里用Web Component搭建的组件库,可以适配vue等语言系统的特性

OMI Web Components
https://omi.cdn-go.cn/home/latest/zh/

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【进阶系列】python的模块

模块 创建一个 .py 文件&#xff0c;这个文件就称之为 一个模块 Module 如何使用 import 想要B.py文件中&#xff0c;使用A.py文件&#xff0c;只需要在B.py文件中使用关键字import导入即可。 import A# 若A是一个包的话&#xff0c;可以这样写 import A.函数名from impor…

全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS编译开发说明

3、RTOS编译开发说明 3.1、RTOS SDK与TinaLinux开发环境 RTOS SDK相关代码已集成到Tina Linux开发环境&#xff0c;Tina Linux开发环境下的rtos子目录即为RTOS开发环境。 ├──brandy ├──bsp ├──build ├──buildroot ├──build.sh >build/top_build.sh ├──…

十六.SpringCloudAlibaba极简入门-整合Grpc代替OpenFeign

前言 他来了他来了&#xff0c;停了快2个月了终于又开始更新文章啦&#xff0c;这次带来的绝对是干货&#xff01;&#xff01;&#xff01;。由于公司项目进行重构的时候考虑到&#xff0c;OpenFeign做为服务通信组件在高并发情况下有一定的性能瓶颈&#xff0c;所以将其替换…

【Linux】环境变量详解

Linux环境变量 1.环境变量分类2.环境变量相关指令3.常用的环境变量4.环境变量的组织方式5.获取环境变量6.命令行参数 1.环境变量分类 按生命周期划分&#xff1a; 永久的&#xff1a;在环境变量脚本文件中配置&#xff0c;用户每次登录时会自动执行这些脚本&#xff0c;相当于永…

SpringBoot项目搭建IEDA2023.1.2

导入依赖 ——————————————————

L0G1000 Linux基础知识(包含ssh报错处理)

1.vscode通过ssh链接云服务器 按教程https://github.com/InternLM/Tutorial/tree/camp4/docs/L0/linux 出现报错&#xff0c;是ssh配置原因 [23:40:18.788] Log Level: 2 [23:40:18.807] SSH Resolver called for “ssh-remotessh.intern-ai.org.cn”, attempt 1 [23:40:18.8…

使用 PyTorch-BigGraph 构建和部署大规模图嵌入的完整教程

当涉及到图数据时&#xff0c;复杂性是不可避免的。无论是社交网络中的庞大互联关系、像 Freebase 这样的知识图谱&#xff0c;还是推荐引擎中海量的数据量&#xff0c;处理如此规模的图数据都充满挑战。 尤其是当目标是生成能够准确捕捉这些关系本质的嵌入表示时&#xff0c;…

测试标题1111

前言 本文是该专栏的第68篇&#xff0c;后面会持续分享python爬虫干货知识&#xff0c;记得关注。 在本专栏之前&#xff0c;笔者有详细介绍京东滑块验证码的解决方法&#xff0c;感兴趣的同学&#xff0c;可以直接翻阅文章《Python如何解决“京东滑块验证码”(5)》进行查看。…

JDK8-17新特性

1.Java8新特性-Lambda表达式 2.1关于Java8新特性简介 Java 8是Java编程语言的一个重大版本更新&#xff0c;于2014年3月发布。它引入了许多新特性和改进&#xff0c;使得Java编程更加方便和高效。 下面是Java 8的主要新特性&#xff1a; Lambda表达式&#xff1a;Lambda表达式…

如何确保Python爬虫程序的稳定性和安全性?

在当今数字化时代&#xff0c;Python爬虫被广泛应用于数据采集和信息抓取。然而&#xff0c;确保爬虫程序的稳定性和安全性是开发过程中的重要考虑因素。本文将探讨如何通过技术手段和最佳实践来提高Python爬虫的稳定性和安全性&#xff0c;并提供代码示例。 稳定性保障 1. 异…

Axure二级菜单下拉交互实例

1.使用boxlabe进行基础布局 2.设置鼠标悬浮和选中状态 3.转换为动态面板 选中所有二级菜单,进行按钮组转换 选中所有二级菜单,进行动态面板转换 4.给用户管理增加显示/隐藏事件 1)选择toggle代表上拉和下拉切换加载 2)勾选Bring to Front,并选择Push/Pull Widgets代表收缩时…

基于智能推荐的图书电商系统的设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

JavaScript实现Promise

第一步&#xff1a;编写constructor构造方法 const PENDING pending; const FULFILLED fulfilled; const REJECTED rejected;class MyPromise {#state PENDING;#result undefined;constructor(executor) {const resolve (data) > {this.#changeState(FULFILLED, data…

物理 + 人工智能 = 2024年诺贝尔物理学奖

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《热点时事》 期待您的关注 目录 引言 一、机器学习与神经网络的发展前景 二、机器学习和神经网络的研究与传统物理学的关系 结…

C++:异常

1. 异常的概念 C语言主要通过错误码的方式处理错误&#xff0c;错误码本质上就是对错误信息进行分类编号&#xff0c;拿到错误码以后还要去查询错误信息&#xff0c;比较麻烦。异常时抛出一个对象&#xff0c;这个对象可以涵盖更全面的信息。 异常处理机制允许程序中独立开发的…

南京邮电大学算法设计-二叉树先序遍历算法动态演示

二叉树先序遍历算法动态演示 一、课题内容和要求 (1)实验目的&#xff1a; 本实验通过手动输入二叉树结点信息&#xff0c;构建相应的二叉树&#xff0c;并通过图形化界面动态演示先序遍历算法的过程。通过本次实验&#xff0c;我可以深入理解二叉树的数据结构、先序遍历算法…

【开源免费】基于Vue和SpringBoot的在线考试系统(附论文)

本文项目编号 T 624 &#xff0c;文末自助获取源码 \color{red}{T624&#xff0c;文末自助获取源码} T624&#xff0c;文末自助获取源码 网络的广泛应用给生活带来了十分的便利。所以把在线考试管理与现在网络相结合&#xff0c;利用java技术建设在线考试系统&#xff0c;实现…

高阶C语言之六:程序环境和预处理

本文介绍程序的环境&#xff0c;在Linux下对编译链接理解&#xff0c;较为简短&#xff0c;着重在于编译的步骤。 C的环境 在ANSI C&#xff08;标准C语言&#xff09;的任何一种实现中&#xff0c;存在两个不同的环境。 翻译环境&#xff1a;在这个环境中&#xff0c;源代码…

HarmonyOs鸿蒙开发实战(10)=>状态管理-对象数组的属性数据变更刷新UI,基于@Observed 和@ObjectLink装饰器

1.条件:基于HarmonyOs5.0.0版本. 2.功能要求&#xff1a;横向列表中每个景点的名称&#xff08;eg: 第二项 “灵隐寺” &#xff09;, 在通过天气接口拿到对应天气后&#xff0c;拼接到名称后面 > 变成&#xff08;“灵隐寺” 天气&#xff09;&#xff09; 3.老规矩先看…

快速上手Mybatis Plus并速通MybatisPlus所有知识点

目录 一、简介 1.1 概况 1.2 特性 二、快速入门 1.建表 2.引依赖 3.application.ymal文件 4.定义mapper继承BaseMapper 5.总结 三、Mybatis Plus的使用 1.常见注解 1.1 TableName 1.2 TableId 1.3 TableField 2.常见配置 3.BaseMapper的基础CRUD方法 4.Wrapper…