您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > HTML

如何编写一个原生 Web Components 组件

时间:2022-10-07 20:25:29  来源:环球网  作者:茶无味的一天

当今前端编程中,利用语义化的 html 结合 css 来完一个组件并不是一件难事,这也意味着无论在 ReactVue 中都可以插入,不过它俩不是今天的主角,接下来我将用一个例子来介绍如何封装一个完整的原生 HTML 的 Web Components 组件,让我们开始吧!

HTML结构

首先我们来了解下 HTML 中的 <detAIls> 元素,它可以用于创建一个小部件,其中包含仅在小部件处于“打开”状态时才可见的附加信息,<details>元素内可以包含的内容没有任何限制。

默认情况下,元素创建的小部件<details>处于“关闭”状态(open标签可使其打开)。通过单击小部件在“打开”和“关闭”状态之间切换,以显示或隐藏标签中包含的附加信息,内部标签 <summary> 元素则可为该部件提供概要。

一个简单的例子如下:

<details>
    <summary> 不能说的秘密 </summary>
    藏的这么深,可还是被你发现了
</details>
details {
    border: 1px solid #aaa;
    border-radius: 4px;
    padding: .5em .5em 0;
}

summary {
    font-weight: bold;
    margin: -.5em -.5em 0;
    padding: .5em;
}

details[open] {
    padding: .5em;
}

details[open] summary {
    border-bottom: 1px solid #aaa;
    margin-bottom: .5em;
}

 

使用语义化 HTML 的优点:页面内容结构更清晰,方便开发者阅读,更利于浏览器的理解与加载,搜索引擎解析与seo优化。

添加亿点样式

原生元素默认的样式很简陋,因此我们需要为其定制一下样式,这块内容我们简单带过,只讲解关键部分,样式内容有省略,具体可以在文末的码上掘金中看到呈现效果。

.ContentWarning > summary {
  position: relative;
  list-style: none; /** 去除默认样式 **/
  user-select: none; 
  cursor: pointer;
  /** 为其添加一个斜线背景 **/
  --stripe-color: rgb(0 0 0 / 0.1);
  background-image: repeating-linear-gradient(45deg,
      transparent,
      transparent 0.5em,
      var(--stripe-color) 0.5em,
      var(--stripe-color) 1em);
}

/** 通过var变量调整悬停时的颜色样式 **/
.ContentWarning>summary: hover,
.ContentWarning>summary: focus {
  --stripe-color: rgb(150 0 0 / 0.1);
}

 

封装模板

现在我们来把它封装成一个完整的组件,这需要先将 HTML 编写在模板 template 当中,并设置一个 id,如下所示:

<template id="warning-card">  
  <details class="ContentWarning">
    <summary>
      <strong>⚠️ 注意:</strong> 以下为隐藏内容
    </summary>
    <slot name="desc"> 藏的这么深,可还是被你发现了 </slot>
  </details>
</template>

熟悉 Vue 的小伙伴应该很容易理解上面的代码,结构很相似,不过网页不会直接渲染它包裹的内容。此外我们还对此模板设置了一个插槽 slot,后面会讲到它的作用。

定义组件

有了上面封装好的模板,我们就需要在 JS 中定义成可用组件来让其能够被使用,调用 window 下的 customElements.define 方法,第一个参数是传入组件名称,我们定义组件名为: warning-card ,第二个参数传入一个继承了 HTMLElement 的类,在其构造方法当中获取并克隆一个新的 HTML 节点,它会通过 AppendChild 渲染到页面当中。

window.customElements.define('warning-card',
  class extends HTMLElement {
    constructor() {
      super();
      var templateElem = document.getElementById('warning-card');
      var content = templateElem.content.cloneNode(true);
      this.appendChild(content);
    }
  })

接着我们就可以在页面中把它当作组件那样使用了:

<warning-card> </warning-card>

插槽与传参

回头看看上面我们模板中设置的插槽 slot,此时还是没有生效的,我们需要稍微改写一下构造函数中的渲染方式,将 web 组件定义为一个 Shadow DOM,这样构造的是一个可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起的独立元素,并在最后使用 Node.cloneNode() 方法添加了模板的拷贝到 Shadow 的根结点上。

window.customElements.define('warning-card',
  class extends HTMLElement {
    constructor() {
      super();
      var template = document.getElementById('warning-card').content;
      this.attachShadow({ mode: 'open' }).appendChild(template.cloneNode(true));
    }
  })

现在我们尝试使用下组件,往其内容添加一个图片,指向名为 desc 的 slot 插槽中:

<warning-card>
  <img slot="desc" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ba825ffee78c4a1b9c0232e5d2f1d048~tplv-k3u1fbpfcp-watermark.image?" />
</warning-card>

这时你会发现,图片插入到 details 元素的隐藏区域当中了,slot 已经成功生效,但是样式却消失了,这时因为组件已经被完全隔离,我们需要将样式作用在其内部才会生效。

<template id="warning-card">
  <style>
    <!-- TODO: 组件的样式 -->
  </style>
  
  <details class="ContentWarning">
    <summary>
      <strong>⚠️ 注意:</strong>
    </summary>
    <slot name="desc">THE DESCRIPTION</slot>
  </details>
</template>

这样组件就正常了:

 

除了定制模板中的插槽,我们也可以通过 HTML 标签属性来实现一些简单的传参,例如在 summary 标签中显示一个标题:

<warning-card title="前方高能">
</warning-card>

我们只需要在模板中定义好这个标题的位置:

<template id="warning-card">
  <details class="ContentWarning">
    <summary>
        <!-- TODO: 模板中加入一个span标签 -->
      <strong>⚠️ 注意:</strong> <span id="title"></span>
    </summary>
  </details>
</template>

最后在构造函数中我们通过 document 的原生方法写入模板中就可以了:

window.customElements.define('warning-card',
  class extends HTMLElement {
    constructor() {
      super();
      var template = document.getElementById('warning-card').content;
      // TODO: 找到title标签,写入传入组件的title属性值
      template.querySelector('#title').innerText = this.getAttribute('title');
      this.attachShadow({ mode: 'open' }).appendChild(template.cloneNode(true));
    }
  })

结束

至此,我们通过一个简单的原生组件学习了如何编写 Web Components,可以在此代码片段中查看具体源码:原生Web Components组件 - 码上掘金原生Web Components组件 - 码上掘金

以上就是文章的全部内容,希望对你有所帮助!如果觉得文章写的不错,可以点赞收藏,也欢迎关注,我会持续更新更多前端有用的知识与实用技巧,我是茶无味de一天,希望与你共同成长~



Tags:Web Components   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  Search: Web Components  点击:(8)  评论:(0)  加入收藏
如何编写一个原生 Web Components 组件
当今前端编程中,利用语义化的 HTML 结合 CSS 来完一个组件并不是一件难事,这也意味着无论在 React、Vue 中都可以插入,不过它俩不是今天的主角,接下来我将用一个例子来介绍如何...【详细内容】
2022-10-07  Search: Web Components  点击:(377)  评论:(0)  加入收藏
▌简易百科推荐
Htmx,它到底是框架还是库?
在最近的前端开发技术的探讨中,htmx经常成为热议的话题。一些人批评它,认为尽管htmx批评现代前端框架过于复杂,但它自己却似乎也是一个复杂的框架。这种看法值得我们深入思考。...【详细内容】
2024-03-28  前端达人  今日头条  Tags:Htmx   点击:(17)  评论:(0)  加入收藏
前端工作方式要换了?HTMX简介:无需JavaScript的动态HTML
HTMX允许你使用扩展的HTML语法代替 JavaScript 来实现交互性。HTMX 在标记中直接为你提供HTTP 交互,并支持许多其他交互需求,无需求助于 JavaScript。这是一个有趣的想法,可能...【详细内容】
2023-10-19  大迁世界  微信公众号  Tags:HTMX   点击:(292)  评论:(0)  加入收藏
HTMX简介:无需借助JavaScript的动态HTML
译者 | 布加迪审校 | 重楼HTML让您可以使用扩展的HTML语法而不是JavaScript来实现交互性。HTMX直接在标记中为您提供了HTTP交互,它支持其他许多交互要求,无需借助JavaScript。...【详细内容】
2023-10-07    51CTO  Tags:HTML   点击:(373)  评论:(0)  加入收藏
htmx:增强版 HTML 来了!
如今,Web 用户期望得到单页应用(SPA)提供的流畅、动态的体验。然而,创建 SPA 往往需要使用复杂的框架,如 React 和 Vue,学习和使用起来可能比较困难。这就是htmx的用武之地:一种通...【详细内容】
2023-09-03  前端充电宝  微信公众号  Tags:htmx   点击:(221)  评论:(0)  加入收藏
加入GitHub Accelerator,htmlx 2.0 要来了!
本文主要向大家介绍 htmlx 加入 GitHub Accelerator,关于 htmlx 的原理,以前有单独发表过文章介绍: 让 React 代码行数减少78%的 htmlx 有这么神?大家有感兴趣的可以阅读,话不多...【详细内容】
2023-08-25  高级前端进阶  今日头条  Tags:htmlx   点击:(365)  评论:(0)  加入收藏
爬虫解析HTML动态JS,技术应用揭秘
在当今互联网时代,大量的信息都储存在了各种网页中。而对于开发者、数据分析师和研究人员来说,获取并分析这些网页中的数据是非常重要的任务之一。然而,随着技术的不断发展,许多...【详细内容】
2023-06-29  反方向的鱼    Tags:HTML   点击:(220)  评论:(0)  加入收藏
利用ChatGPT辅助处理Html数据
使用chatgpt进行辅助编程首先要清晰描述自己需求,生成代码通过不断调试及优化,最终完成任务。有它,对程序员是好事也是坏事。一、确认功能请编程实现以下功能:1.所有html保存在a...【详细内容】
2023-05-31    51CTO  Tags:Html   点击:(422)  评论:(0)  加入收藏
一篇文章带你学会HTML以及最常用的标签
HTML是一种标记语言,用于创建网页。在本文中,我们将介绍HTML的基础知识,代码写入到本地文件,并以.html结尾,双击浏览器打开就可以查看效果。HTML文档结构HTML文档由标签组成,每个...【详细内容】
2023-05-16  你的老师父  今日头条  Tags:HTML   点击:(374)  评论:(0)  加入收藏
HTML代码混淆技巧:让爬虫无法抓取,保护你的网页!
随着互联网的发展,越来越多的网站开始使用爬虫技术来获取数据。但是,有些网站为了保护自己的数据安全,会对HTML代码进行混淆处理,使得爬虫无法直接抓取数据。本文将介绍HTML代码...【详细内容】
2023-04-13  倪沛童    Tags:HTML   点击:(239)  评论:(0)  加入收藏
HTML5第三节 初学者接触列表标签和div标签以及span标签
<ul> <li>为列表标签此为无序列表<type=“?”> <apuare>正方形<circle>空心圆环 <disc>默认 实心园 <ol> <li>为列表标签此为有序列表<type=“?”> <1> <a> <A>等 <dl> <dt>...【详细内容】
2023-02-07  那般热衷是你  今日头条  Tags:HTML5   点击:(228)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条