使用自定义标签和 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)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月21日 21:34:23
下一篇 2025年12月21日 21:34:38

相关推荐

  • 如何使用HTML5创建一个变换矩阵?

    In the following article, we are going to learn about how to create a transformation matrix with HTML5. HTML5 canvas provides methods that allow modif…

    好文分享 2025年12月21日
    000
  • HTML5中的Canvas免费库有哪些?

    使用脚本,canvas元素用于立即创建图形(通常是JavaScript)。该标签是 HTML5 中刚刚引入的。 元素仅用作图像的保存区域。要绘制视觉效果,您必须使用脚本。有多种方法可以在画布上绘制路径、方框、圆圈、字符以及添加图像。 语法 这是一个简单的 HTML 示例来描述画布的用法 &#8211…

    2025年12月21日
    000
  • HTML中GET和POST方法的区别

    在这篇文章中,我们将了解 HTML 中 GET 和 POST 方法的区别。 GET 方法 参数放置在 URL 内。 其主要目标是检索其中存在的数据/文档。 它能够为查询结果添加书签。 立即学习“前端免费学习笔记(深入)”; 它很容易受到攻击,而且不够安全。 这是因为数据和凭据以纯文本形式呈现。 任何…

    2025年12月21日
    000
  • 在HTML5中,当触发上下文菜单时执行脚本?

    使用 HTML5 中的 contextmenu 属性在上下文菜单打开时执行脚本。当用户右键单击时会生成上下文菜单。 示例 您可以尝试运行以下代码来实现contextmenu属性 – HTML menuitem Tag Right click inside here…. 视野自助系统小…

    2025年12月21日 好文分享
    000
  • html的注释符号是哪个

    html的注释符号是“”,注释符号之间的内容将被视为注释,不会被浏览器解析和显示,注释可以包含任何文本,包括说明、备注、代码片段等,注释可以用于添加注释、临时禁用代码、添加调试信息和解决浏览器兼容性问题,以便开发人员可以更好地理解和管理代码,注释的内容不会在浏览器中显示,可以合理地使用注释,以提高代…

    2025年12月21日
    000
  • iframe监听事件有哪些

    iframe监听事件有onload事件、onunload事件、onbeforeunload事件、onmessage事件以及onerror事件等。详细说明:1、添加onload事件,当iframe中的内容加载完成时触发;2、添加onunload事件,当iframe中的内容被卸载时触发;3、添加onbe…

    2025年12月21日
    000
  • iframe有哪些加载事件

    iframe的加载事件有onload事件、onreadystatechange事件、onbeforeunload事件、onerror事件、onabort事件等。详细说明:1、onload事件,指定加载iframe完成后要执行的JavaScript代码;2、onreadystatechange事件,指…

    2025年12月21日
    000
  • 前端框架除了iframe还有哪些

    前端框架除了iframe还有React、Angular、Vue、Ember和Backbone等框架。详细介绍:1、React,采用了组件化的开发模式,使开发人员能够将应用程序拆分为独立的可重用组件;2、Angular,提供了一套强大的工具和功能,用于构建复杂的Web应用程序,还有一套丰富的指令和组件…

    2025年12月21日
    000
  • 为什么iframe嵌套百度不存在跨域问题

    iframe嵌套百度不存在跨域的原因是百度主页设置了Access-Control-Allow-Origin字段允许跨域访问。当我们在一个网页中嵌套百度主页时,浏览器会发送一个请求到百度服务器,百度服务器会返回一个带有Access-Control-Allow-Origin字段的响应头,浏览器会检查这个…

    2025年12月21日
    000
  • iframe什么情况下会跨域

    iframe在以下几种情况会跨域:1、域名不同,当iframe的源域名与父页面的域名不同时,会发生跨域问题;2、协议不同,当iframe的协议与父页面的协议不同时,会发生跨域问题;3、端口号不同,当iframe的端口号与父页面的端口号不同时,会发生跨域问;4、子域名不同,当iframe的子域名与父页…

    2025年12月21日
    000
  • 如何在JavaScript中使用document.title?

    使用 document.title 属性在 JavaScript 中设置文档的标题。 示例 您可以尝试运行以下代码以在 JavaScript 中实现 document.title 属性。 实时演示 Demo Title var x = document.title; document.write(“…

    2025年12月21日
    000
  • 同源iframe什么意思

    同源iframe的意思是指在同一个域名下的不同网页之间嵌套的iframe元素。通过使用同源iframe,可以实现不同源网页之间的通信和交互,当一个网页通过iframe嵌入另一个网页时,嵌入的网页被视为同源的,可以自由地与父网页进行通信和交互,包括读取和修改父网页的内容。在使用同源iframe时,需要…

    2025年12月21日
    000
  • 我们如何在HTML中创建一个图像映射?

    要添加图像映射,请使用 HTML 中的 标记。 HTML 标签与 标签一起定义图像映射。 以下是属性 – 属性 值 说明 立即学习“前端免费学习笔记(深入)”; 立即学习“前端免费学习笔记(深入)”; tr>名称 unique_name 定义地图标记的唯一名称 示例 您可以尝试运行…

    2025年12月21日
    000
  • HTML DOM Input Range对象

    html dom输入范围对象与具有类型“range”的元素相关联。我们可以使用createelement()和getelementbyid()方法分别创建和访问类型为range的输入元素。 属性 以下是Input范围对象的属性: 序号 属性和描述 1autocomplete 设置或返回范围控件的自动…

    2025年12月21日
    000
  • 如何在JavaScript中将Unicode值转换为字符?

    在本教程中,我们将学习在 JavaScript 中将 Unicode 值转换为字符。 Unicode值是字符的标准值,用户可以对其进行编码以将其转换为字符。 例如,“A”是一个 Unicode 字符,根据 ASCII(美国信息交换标准代码)其值为 65桌子。同样,所有字母、数字和其他字符都有特定的 …

    2025年12月21日
    000
  • 如何使用HTML和CSS创建粘性球动画?

    粘球动画是一种使用HTML和CSS创建的动画。此动画样式是通过使用关键帧指定动画中不同点的CSS属性值,然后将动画应用到HTML元素来创建的。 Gooey balls是一种使用HTML和CSS创建的流行且视觉上吸引人的动画风格。在这个动画中,我们为一个圆形对象创建了一个平滑、流动和弹性的效果,使它看…

    2025年12月21日
    000
  • 使用HTML和CSS创建印度国旗

    我们知道HTML和CSS是用于网络和设计的语言,但我们可以做的远不止制作网页应用。例如,我们还可以使用它们制作一个有趣的项目,这将需要对这两种语言的深入了解。 所以,我们手头的任务是使用HTML和CSS来创建印度国旗。无论我们想要创建什么类型的国旗,都会有两个部分:第一个是旗杆,第二个是旗帜本身。正…

    2025年12月21日
    000
  • 利用WordPress媒体上传工具添加和删除图片

    在本系列的上一篇文章中,我们开始使用 wordpress 媒体上传器的最新版本,以便更清楚地了解如何开始将其合并到我们的项目中。 使用这个新功能(嗯,是 3.5 以后的新功能)的困难之处在于它没有像其他功能那样有详细的文档记录。这显然让很多开发人员——尤其是初学者——对如何开始使用它感到摸不着头脑。…

    2025年12月21日
    000
  • link标签和import有什么区别

    link标签和import的区别有语法和用途、功能和特性、加载时机、兼容性和支持等。详细介绍:1、语法和用途,link标签是HTML标签,用于在HTML文档中引入外部资源,如CSS样式表、JavaScript脚本、图标等,import是ES6中的模块导入语法,用于在JavaScript文件中引入外部…

    2025年12月21日
    000
  • 当浏览器窗口大小发生改变时,在HTML中执行一个脚本吗?

    当网页浏览器窗口大小调整时,onresize 属性会触发。 示例 您可以尝试运行以下代码实现 onresize 属性 – Resize the window to trigger event. function display() { alert(“Web browser window …

    2025年12月21日
    000

发表回复

登录后才能评论
关注微信