共计 3591 个字符,预计需要花费 9 分钟才能阅读完成。
在明天的前端编程中,利用语义化的 HTML 联合 CSS 来完一个组件并不是一件难事,这也意味着无论在 React、Vue 中都能够插入,不过它俩不是明天的配角,接下来我将用一个例子来介绍如何封装一个残缺的原生 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,能够在此代码片段中查看具体源码。
以上就是文章的全部内容,心愿对你有所帮忙!如果感觉文章写的不错,能够点赞珍藏,也欢送关注,我会继续更新更多前端有用的常识与实用技巧,我是茶无味 de 一天,心愿与你独特成长~