使用自定义标签和 Shadow DOM 增强 HTML

使用自定义标签和 shadow dom 增强 html

在上一篇文章中,我解释了创建自定义标签的基础知识。事实上,自定义标签消除了构建优秀 Web 应用程序时的一些脆弱性。然而,对控制的追求并没有停止,传统的自定义标签不足以构建性能丰富的应用程序。例如,代码中样式选择器的数量可能会随着自定义标签的增加而增加。这只是可能导致性能问题的众多因素之一。

解决此问题的一种方法是通过 Shadow DOM。

Shadow DOM 通过引入作用域样式来工作。它不需要任何特殊的命名约定或工具。使用 Shadow DOM,将 CSS 与标记捆绑起来变得很简单。此外,此功能允许我们隐藏有关普通 JavaScript 中实现的所有细节。

为什么使用 Shadow DOM?

Shadow DOM 提供以下解决方案:

立即学习“前端免费学习笔记(深入)”;

允许 DOM 中的独立元素。诸如 document.querySelector 之类的查询不会返回孤立的元素。允许作用域 CSS。作用域 CSS 确保所有样式规则都保留在页面内。它还意味着更简单的 CSS 选择器,没有任何命名冲突和许多通用类。

我们的示例

为了演示 Shadow DOM,我们将使用一个名为 tuts-tabs 的简单组件。本文中的所有引用都将指向这段代码。要体验 Shadow DOM,请看下面的演示:

了解 Shadow DOM

什么是 Shadow DOM?

开始使用 Shadow DOM 进行编码之前,您需要了解常规 DOM。

HTML 是网站的支柱。只需几分钟,您就可以创建一个页面。当您在浏览器中打开该页面时,DOM 开始发挥作用。一旦浏览器加载页面,它就会开始将 HTML 解析为数据模型。该数据模型是一个树结构,其中的节点代表 HTML 中的元素。该数据模型很容易用代码修改和操作。

缺点是整个网页甚至复杂的 Web 应用程序都会被视为单个数据结构。这不太容易调试!例如,适用于一个组件的 CSS 样式最终可能会影响应用程序中其他位置的另一个组件。

当您想要将界面的一部分与其余部分隔离时,可以使用 iframes。但 iframe 很重并且限制性极大。

这就是引入 Shadow DOM 的原因。它是现代浏览器的一项强大功能,允许 Web 开发人员在 DOM 中包含各种元素的子树。 DOM 的这些子树不会影响主文档树。从技术上讲,它们被称为影子树

影子树有一个影子根,它附加到 DOM 中的父级。该父级称为影子主机

例如,如果您将 插入由 WebKit 提供支持的浏览器,它将转换为滑块。为什么?这是一个滑块,因为子树 DOM 元素之一了解“范围”以更改其外观并引入类似滑块的功能。这是 Shadow DOM 给选项卡带来的一个优势。

哇,这是很多理论。现在,您可能想要编写一些代码来了解如何实现 Shadow DOM。

使用 Shadow DOM 的分步指南

第 1 步:创建 Shadow DOM 元素

使用 element.attachShadow() 创建 Shadow DOM 元素。

在我们的示例 tuts-tab 中,您将看到用于创建 Shadow DOM 元素的代码。

 let shadowRoot = this.attachShadow({mode: 'open'});

第 2 步. 将内容添加到 Shadow Root

接下来,我们将使用 .innerHTML 将内容添加到影子根目录。请注意,这不是填充 Shadow DOM 的唯一方法。有许多 API 可以帮助您填充 Shadow DOM。

shadowRoot.innerHTML = ``

第 3 步:将自定义元素连接到 Shadow DOM

将自定义元素连接到 Shadow DOM 非常简单。请记住,当您将自定义元素与 Shadow DOM 组合时,您将能够使用 CSS、JavaScript 和 HTML 创建封装组件。因此,您将创建一个可以在您的应用程序中重用的全新 Web 组件。

在我们的示例中,我们使用 customElements.define() 创建一个新的自定义元素。正如上一教程中提到的,新元素的名称中应包含“-”。 tuts-tabs 组件扩展了 HTMLElement

当我们扩展 HTMLElement 时,在构造函数中调用 super() 非常重要。另外,构造函数是需要创建 shadowRoot 的地方。

customElements.define('tuts-tabs', class extends HTMLElement {    constructor() {    super(); // always call super() first in the constructor.    // Attach a shadow root to .    const shadowRoot = this.attachShadow({mode: 'open'});    ...});

创建 shadowRoot 后,您可以为其创建 CSS 规则。 CSS 规则可以包含在 标记中,并且这些样式的范围仅限于 tuts-tab

customElements.define('tuts-tabs', class extends HTMLElement {    constructor() {    super();     const shadowRoot = this.attachShadow({mode: 'open'});    shadowRoot.innerHTML = `                  #tabs { ... }    `;    }    ...});

第 4 步:向 Shadow DOM 添加样式

tuts-tab相关的CSS可以写在标签内。请记住,此处声明的所有样式都将作用于 tuts-tab Web 组件。 作用域 CSS 是 Shadow DOM 的一项有用功能,它具有以下属性:

CSS 选择器不会影响 Shadow DOM 之外的组件。Shadow DOM 中的元素不受其外部选择器的影响。样式的范围仅限于宿主元素。

如果你想在 Shadow DOM 中选择自定义元素,你可以使用 :host 伪类。当 :host 伪类用于普通 DOM 结构时,它不会产生任何影响。但在 Shadow DOM 内部,它会产生很大的差异。您将在 tuts-tab 组件中找到以下 :host 样式。它决定显示和字体样式。这只是一个简单的示例,展示如何将 :host 合并到 Shadow DOM 中。

:host 的一个问题是它的特殊性。如果父页面有 :host,它将具有更高的特异性。父样式内的所有样式都会获胜。这是从外部覆盖自定义元素内部样式的一种方法。

 :host {  display: inline-block;  width: 650px;  font-family: 'Roboto Slab';  contain: content;}

随着 CSS 变得更简单,Shadow DOM 的整体效率也会提高。

下面定义的所有样式都是影子根的本地样式。

shadowRoot.innerHTML = `:host {  display: inline-block;  width: 650px;  font-family: 'Roboto Slab';  contain: content;}#panels {  box-shadow: 0 2px 2px rgba(0, 0, 0, .3);  background: white;  border-radius: 3px;  padding: 16px;  height: 250px;  overflow: auto;}#tabs slot {  display: inline-flex; /* Safari bug. Treats  as a parent */}...

同样,您可以自由地在 Shadow DOM 中引入样式表。当您在 Shadow DOM 内链接样式表时,它们的作用域将位于 Shadow 树内。这是一个简单的例子来帮助您理解这个概念。

shadowRoot.innerHTML = `:host {  display: inline-block;  width: 650px;  font-family: 'Roboto Slab';  contain: content;}#panels {  box-shadow: 0 2px 2px rgba(0, 0, 0, .3);  background: white;  border-radius: 3px;  padding: 16px;  height: 250px;  overflow: auto;}......

步骤 5. 在自定义组件中定义 HTML 元素

接下来,我们可以定义 tuts-tab 的 HTML 元素。

在简单的选项卡结构中,应该有可单击的标题和反映所选标题内容的面板。这显然意味着我们的自定义元素应该有一个带有标题的 div 和一个用于面板的 div 。 HTML 组件将定义如下:

customElements.define('tuts-tabs', class extends HTMLElement {    constructor() {    super(); const shadowRoot = this.attachShadow({mode: 'open'});    shadowRoot.innerHTML = `        #tabs { ... }                ....                // Our HTML elements for tuts-tab        
...
...
... `; } ...});

在面板的 div 中,您会遇到一个有趣的标签,名为 。我们的下一步是了解有关插槽的更多信息。

第 6 步:在 Shadow DOM 中使用槽

Slot 在 Shadow DOM API 中起着至关重要的作用。插槽充当自定义组件内的占位符。这些组件可以由您自己的标记填充。槽声明分为三种不同类型:

您可以拥有零个插槽的组件。 您可以创建一个包含后备内容或空内容的槽位。 您可以使用整个 DOM 树创建槽。

在我们的 tuts-tabs 中,我们有一个用于选项卡标题的命名槽,以及另一个用于面板的槽。命名槽会创建您可以通过名称引用的孔。

customElements.define('tuts-tabs', class extends HTMLElement {    constructor() {    super(); const shadowRoot = this.attachShadow({mode: 'open'});    shadowRoot.innerHTML = `        #tabs { ... }                ....                // Our HTML elements for tuts-tab        
... `; } ...});

第 7 步:填充插槽

现在,是时候填充插槽了。在之前的教程中,我们了解了定义自定义元素的四种不同方法,并且 tuts-tabs 使用其中两种方法来构建选项卡:connectedCallbackdisconnectedCallback

connectedCallback 中,我们将填充步骤 6 中定义的槽。我们的 connectedCallback 将定义如下。我们使用 querySelector 来识别 tabsSlotpanelsSlot。当然,这并不是识别 HTML 中插槽的唯一方法。

识别槽后,您需要为其分配节点。在 tuts-tab 中,我们使用以下 tabsSlot.assignedNodes 来标识选项卡的数量。

connectedCallback() {    ...    const tabsSlot = this.shadowRoot.querySelector('#tabsSlot');    const panelsSlot = this.shadowRoot.querySelector('#panelsSlot');    this.tabs = tabsSlot.assignedNodes({flatten: true});    this.panels = panelsSlot.assignedNodes({flatten: true}).filter(el => {      return el.nodeType === Node.ELEMENT_NODE;    });    ...  }

此外,connectedCallback 是我们注册所有事件监听器的地方。每当用户单击选项卡标题时,面板的内容都需要更改。可以在 connectedCallback 函数中注册用于实现此目的的事件侦听器。

第 8 步:实现逻辑和交互性

我们不会深入探讨如何实现选项卡及其功能的逻辑。但是,请记住,我们的自定义 tuts-tab 组件中实现了以下方法,用于在选项卡之间切换:

onTitleClick 该方法捕获选项卡标题上的点击事件。它有助于在选项卡面板内切换内容。selectTab该函数负责隐藏面板和显示右侧面板。此外,它还负责突出显示所选的选项卡。findFirstSelected此方法用于在第一次加载时选择选项卡。selected这是一个用于获取所选选项卡的 getter 和 setter。

第 9 步.定义生命周期方法

继续,不要忘记定义 disconnectedCallback。这是自定义元素中的生命周期方法。当自定义元素从视图中销毁时,会触发此回调。这是在应用程序中删除操作侦听器和重置控件的最佳位置之一。但是,回调的范围仅限于自定义元素。在我们的例子中,它将是 tuts-tab

第 10 步。使用新组件!

最后一步是在 HTML 中使用 tuts-tab 。我们可以很容易地在 HTML 标记中插入 tuts-tab 。这是一个简单的例子来演示其用法。

        
content panel 1
content panel 2
content panel 3

结论

我们开始了!我们已经完成了一个重要教程,在该教程中我们创建并使用了自定义元素。该过程很简单,并且在开发网页时被证明非常有用。我希望您尝试创建自定义元素并与我们分享您的经验。

以上就是使用自定义标签和 Shadow DOM 增强 HTML的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1551297.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
HTML5中的Canvas免费库有哪些?
上一篇 2025年12月21日 21:34:23
如何使用HTML5创建一个变换矩阵?
下一篇 2025年12月21日 21:34:38

相关推荐

  • composer require-dev和require有什么不同_Composer Require与Require-Dev区别解析

    require用于声明项目运行必需的依赖,如框架、数据库组件和第三方SDK,这些包会随项目部署到生产环境;2. require-dev用于声明仅在开发和测试阶段需要的工具,如PHPUnit、PHPStan、Faker等,不会默认部署到生产环境;3. 安装时composer install根据环境决定…

    2026年5月10日
    1000
  • 修复Django电商项目中AJAX过滤产品列表图片不显示问题

    在Django电商项目中,当使用AJAX动态加载过滤后的产品列表时,常遇到图片无法正常显示的问题。这通常是由于前端模板中图片加载方式(如data-setbg属性结合JavaScript库)与AJAX动态内容更新机制不兼容所致。解决方案是直接在AJAX返回的HTML中使用标准的标签来渲染图片,确保浏览…

    2026年5月10日
    000
  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • CSS动画指南:手把手教你制作快速闪烁特效

    CSS动画指南:手把手教你制作快速闪烁特效 CSS动画是网页设计中常用的技术之一,通过CSS属性的过渡和变化,能够为网页增添生动和吸引力。其中,快速闪烁特效是一种常见而又引人注目的效果,本文将为您详细介绍如何利用CSS实现这一特效,并提供具体的代码示例。 在开始之前,我们先明确一下快速闪烁特效的效果…

    2026年5月10日
    000
  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 利用海象运算符简化条件赋值:Python教程与最佳实践

    本文旨在探讨Python中海象运算符(:=)在条件赋值场景下的应用。通过对比传统if/else语句与海象运算符,以及条件表达式,分析海象运算符在简化代码、提高可读性方面的优势与局限性。并通过具体示例,展示如何在列表推导式等场景下合理使用海象运算符,同时强调其潜在的复杂性及替代方案,帮助开发者更好地掌…

    2026年5月10日
    100
  • Debian syslog性能优化技巧有哪些

    提升Debian系统syslog (通常基于rsyslog)性能,关键在于精简配置和高效处理日志。以下策略能有效优化日志管理,提升系统整体性能: 精简配置,高效加载: 在rsyslog配置文件中,仅加载必要的输入、输出和解析模块。 使用全局指令设置日志级别和格式,避免不必要的处理。 自定义模板: 创…

    2026年5月10日
    000
  • 怎么在PHP代码中实现图片上传功能_PHP图片上传功能实现与安全处理教程

    首先创建含enctype的HTML表单,再用PHP接收文件,检查目录、移动临时文件,验证类型与大小,生成唯一文件名,并调整php.ini限制以确保上传成功。 如果您尝试在PHP项目中添加图片上传功能,但服务器无法正确接收或保存文件,则可能是由于表单配置、文件处理逻辑或安全限制的问题。以下是实现该功能…

    2026年5月10日
    100
  • 网页设计服务终极指南

    对于任何追求在线成功的企业来说,拥有一个迷人且实用的网站至关重要。在 Arham Web Works,我们了解创建网页设计的复杂性,不仅能吸引访问者,还能将他们转化为忠实的客户。我们的网页设计方法是全面的,将美学吸引力与无缝功能相结合。本指南将深入探讨网页设计服务的关键方面,展示为什么我们的专业知识…

    2026年5月10日
    200
  • 获取日期中的周数:CodeIgniter 教程

    本教程旨在帮助开发者在 CodeIgniter 框架中,从日期字符串中准确提取周数。我们将使用 PHP 内置的 DateTime 类,并提供详细的代码示例和注意事项,确保您能够轻松地在项目中实现此功能。 使用 DateTime 类获取周数 PHP 的 DateTime 类提供了一种便捷的方式来处理日…

    2026年5月10日
    100
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • 如何让动态追加元素的类事件生效?

    如何在追加元素后使其绑定类事件生效 在页面中引入三方 JavaScript 类并通过添加相应 class 来调用事件方法是一种常见的做法。然而,如果通过 JavaScript 追加标签元素,即使添加了对应的 class,事件也可能无法生效。 为了解决这个问题,可以尝试以下步骤: 检查追加的标签是否为…

    2026年5月10日
    000
  • HTML如何隐藏滚动条或去除滚动条

    滚动条可以存在也可以不存在,本文主要介绍了html 隐藏滚动条和去除滚动条的方法的相关资料,大家一起来学习一下html隐藏滚动条或去除滚动条的方法吧。 1. html 标签加属性 XML/HTML Code复制内容到剪贴板 2.body中加入以下代码 立即学习“前端免费学习笔记(深入)”; html…

    用户投稿 2026年5月10日
    100
  • Golang gRPC流式请求异常处理

    在Golang的gRPC流式通信中,必须通过context.Context处理异常。应监听上下文取消或超时,及时释放资源,设置合理超时,避免连接长时间挂起,并在goroutine中通过context控制生命周期。 在使用 Golang 和 gRPC 实现流式通信时,异常处理是确保服务健壮性的关键部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • vscode上怎么运行html_vscode上运行html步骤【指南】

    首先保存文件为.html格式,再通过浏览器或Live Server插件打开预览;推荐安装Live Server实现本地服务器运行与实时刷新,提升开发体验。 在 VS Code 上运行 HTML 文件并不需要复杂的配置,只需几个简单步骤即可预览页面效果。VS Code 本身是一个代码编辑器,不直接运行…

    2026年5月10日
    100
  • css max-height属性怎么用

    max-height 属性设置元素的最大高度。 说明 该属性值会对元素的高度设置一个最高限制。因此,元素可以比指定值矮,但不能比其高。不允许指定负值。 注意:max-height 属性不包括外边距、边框和内边距。 立即学习“前端免费学习笔记(深入)”; 值描述none 默认。定义对元素被允许的最大高…

    2026年5月10日
    100
  • 怎么把TXT文档转换为(html)网页格式

    很多人想把txt文档转为html,但是却不知道怎么把txt转为html,下面为你推荐一款比较好用的转换器,并且可以把所有的文档都可以转为html格式的,下面我们看一下如何把TXT转化为html格式的文档。 1.首先我们在百度上搜索PDF转换器,我们一定要到正规的网站上下载,一般正规的网站的上的软件都…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信