Web 原生组件化方案:Web Components

news/2024/9/19 5:54:24/ 标签: 前端, javascript

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

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>javascript">// 自定义元素类class HelloWorld extends HTMLElement {constructor() {super()// 创建一个影子DOMconst 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>javascript">  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>javascript">class CustomCard extends HTMLElement {constructor() {super()// 创建影子DOMconst 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.ppmy.cn/news/1523330.html

相关文章

【阿雄不会写代码】全国职业院校技能大赛GZ036第十套

也不说那么多了&#xff0c;要用到这篇博客&#xff0c;肯定也知道他是干嘛的&#xff0c;给博主点点关注点点赞&#xff01;&#xff01;&#xff01;这样博主才能更新更多免费的教程&#xff0c;不然就直接丢付费专栏里了&#xff0c;需要相关文件请私聊

Java进阶13讲__第12讲_2/2

线程安全问题 线程同步方案 线程池 线程通信 理论补充 1. 线程安全问题 1.1 举例说明 1.2 代码实现 package com.itheima.a_线程安全;/* 线程安全:多个线程同时修改同一个资源取钱案例小明和小红是一对夫妻&#xff0c;他们有一个共同的账户&#xff0c;余额是10万元如…

《React Native 应用开发最佳实践》

⭐️React Native 应用开发最佳实践⭐️ 近年来&#xff0c;React Native 应用开发因其能够使用 JavaScript 构建原生移动应用的能力而大受欢迎。它提供了跨平台兼容性、更快的开发时间以及更易于维护的特性&#xff0c;成为了许多开发者的首选。然而&#xff0c;要确保 React…

免费的 Mac 应用清理工具Pearcleaner v3.8.6

免费的 Mac 应用清理工具。这是一款免费开源的 Mac 应用清理工具&#xff0c;能够彻底卸载应用并清理残留文件。它采用 SwiftUI 开发&#xff0c;提供了简单易用的界面&#xff0c;支持右键卸载、迷你模式和 Homebrew 清理等功能。 下载链接&#xff1a;https://pan.quark.cn/s…

计算机网络(三) —— 简单Udp网络程序

目录 一&#xff0c;初始化服务器 1.0 辅助文件 1.1 socket函数 1.2 填充sockaddr结构体 1.3 bind绑定函数 1.4 字符串IP和整数IP的转换 二&#xff0c;运行服务器 2.1 接收 2.2 处理 2.3 返回 三&#xff0c;客户端实现 3.1 UdpClient.cc 实现 3.2 Main.cc 实现 …

前端面试热点题目——typescript篇

在TypeScript面试中&#xff0c;面试官通常会考察你对TypeScript特性的理解、类型系统的掌握、以及在实际项目中的应用能力。以下是一些热点题目及其相应的代码示例&#xff0c;旨在帮助你准备TypeScript相关的面试。 1. 类型别名与接口的区别及使用场景 问题&#xff1a;请解…

react js 笔记 3

起因&#xff0c; 目的: 专注。 学习 react js 的时候&#xff0c; 就专注这一方面 &#xff0c;其他都不要碰。 比如&#xff0c; python, C语言&#xff0c; R, 都不看。 只看 js.专注&#xff0c;减少来回切换。 重复。 自己写的笔记&#xff0c;需要反复多看几遍&#xff…

java开发后端

1.BeanUtils.toBean 方法 它是一个常见的 Java 工具方法&#xff0c;用于将一个 JavaBean 对象转换为另一个 JavaBean 对象 FlowOrderDO flowOrder BeanUtils.toBean(createReqVO, FlowOrderDO.class); 这行代码使用了 BeanUtils.toBean 方法&#xff0c;它是一个常见的 Ja…

MySQL笔记2(DQL查询语言【条件、分组、排序、限制、子查询、左右连接、内连接、联合查询】)

DQL数据查询语言与项目高级查询实战 先安装数据库并创建一个库 并创建以下数据 /*创建部门表*/CREATE TABLE dept( deptnu INT PRIMARY KEY comment 部门编号, dname VARCHAR(50) comment 部门名称, addr VARCHAR(50) comment 部门地址 );/*某个公司的员工表*/ CREATE TABLE…

html备忘录

备忘录 网站收藏数据&#xff1a; 网站收藏.js const webLinks [{ title: "智能翻译", src: "https://fanyi.baidu.com" },{ title: "哔哩哔哩", src: "https://www.bilibili.com" },{ title: "百度一下&#xff0c;你就知道&…

漫谈设计模式 [9]:外观模式

引导性开场 菜鸟&#xff1a;老鸟&#xff0c;我最近在做一个项目&#xff0c;感觉代码越来越复杂&#xff0c;我都快看不懂了。尤其是有好几个子系统&#xff0c;它们之间的调用关系让我头疼。 老鸟&#xff1a;复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你…

微信支付开发避坑指南

1 微信支付的坑 1.1 不能用前端传递过来的金额 订单的商品金额要从数据库获取&#xff0c;前端只传商品 id。 1.2 交易类型trade type字段不要传错 v2版API&#xff0c;不同交易类型&#xff0c;要调用的支付方式也不同。 1.3 二次签名 下单时&#xff0c;在拿到预支付交…

记录深度学习量化操作

0. 简介 深度学习中做量化提升运行速度是最常用的方法&#xff0c;尤其是大模型这类非常吃GPU显存的方法。一般是高精度浮点数表示的网络权值以及激活值用低精度&#xff08;例如8比特定点&#xff09;来近似表示达到模型轻量化&#xff0c;加速深度学习模型推理&#xff0c;目…

MySQL表的操作与数据类型

目录 前言 一、表的操作 1.创建一个表 2.查看表的结构 3.修改表 4.删除一个表 二、 MySQL的数据类型 0.数据类型一览&#xff1a; 1.整数类型 2.位类型 3.小数类型 4.字符类型 前言 在MySQL库的操作一文中介绍了有关MySQL库的操作&#xff0c;本节要讲解的是由库管理的结构——…

TinyWebSever源码逐行注释(三)_ thread_pool.cpp

前言 项目源码地址 项目详细介绍 项目简介&#xff1a; Linux下C轻量级Web服务器&#xff0c;助力初学者快速实践网络编程&#xff0c;搭建属于自己的服务器. 使用 线程池 非阻塞socket epoll(ET和LT均实现) 事件处理(Reactor和模拟Proactor均实现) 的并发模型使用状态机…

python基础语法四-数据可视化

书接上回&#xff1a; python基础语法一-基本数据类型 python基础语法二-多维数据类型 python基础语法三-类 1. plot函数绘制简单折线图 (1)需要的模块&#xff1a;matplotlib.pyplot (2)语法&#xff1a;matplotlib.pyplot.plot(x, y, format_string, **kwargs) x: x轴数…

C语言程序设计-练习篇

不知道结果仍义无反顾地才是勇士。 三&#xff0c;打印整数二进制的奇数位和偶数位 题目内容&#xff1a; 获取一个整数二进制序列中所有的奇数位和偶数位&#xff0c;分别打印出二进制序列 #include <stdio.h>//打印整数二进制的奇数位和偶数位 int main() {int i 0…

C语言从头学55——学习头文件errno.h、float.h

1、头文件 errno.h 中的变量 errno 的使用 在 errno.h 定义了一个 int 类型的变量 errno&#xff08;错误码&#xff09;&#xff0c;如果发现这个变量出现非零值&#xff0c;表示已经执行的函数发生了错误。这个变量一般多用于检查数学函数运算过程中发生的错误。 …

Vue面试题——项目介绍以及SPA介绍

谈谈你开发的项目背景与、架构和技术栈 项目背景 假设我们正在开发一个名为“智慧旅游助手”的Web平台。该平台旨在为用户提供一站式的旅游服务&#xff0c;包括目的地推荐、酒店预订、行程规划、在线购票&#xff08;如门票、机票&#xff09;、旅游攻略分享以及基于地理位置…

不到200行代码,一键写出简单贪吃蛇网页游戏!附详细代码!快来看看吧!

​哈喽大家好&#xff0c;这里是大白百宝阁&#xff0c;每天分享一段小代码~ 今天要分享的是&#xff0c;不到200行代码&#xff0c;制作html版贪吃蛇&#xff0c;效果如下&#xff1a; 游戏结束后&#xff0c;还会显示&#xff1a; 代码如下&#xff1a; <!DOCTYPE html&g…