这项技术仍是比较容易理解的;顾名思义,自定义标签就是 HTML
元素,好比 <div>
、<section>
或 <article>
, 可是咱们能够经过浏览器 API 本身命名。自定义元素就像那些标准的 HTML 元素同样(名字在尖括号中) ,只不过它们老是有一个破折号,好比 <news-slider>
或 <bacon-cheeseburger >
。这么作的目的是为了防止与原生内置标签产生冲突。javascript
自定义元素包含本身的语义、行为、标记,能够在框架和浏览器之间共享。css
class MyComponent extends HTMLElement {
connectedCallback() {
this.innerHTML = `<h1>Hello world</h1>`
}
}
customElements.define('my-component', MyComponent)
复制代码
在这个例子中,咱们定义了咱们本身的 HTML 元素 <my-component>
。诚然,它并无作不少工做,但这是定制元素的基本构建块。全部自定义元素都必须以某种方式扩展 HTMLElement
,才能在浏览器中注册并使用。html
在编码中,没有依赖任何第三方框架,浏览器厂商在升级时,也在致力于规范的向下兼容,几乎保证了按照规范编写的组件不会受到破坏API变化的影响。更重要的是,这些组件一般能够用于当今最流行的框架,包括 Angular、 React、 Vue 和其余框架。更多java
Shadow DOM
是 DOM
的封装版本。这使得开发者能够有效地将 DOM
片断彼此隔离开来,包括任何能够用做 CSS
选择器的内容以及与它们相关的样式。一般,文档做用域内的任何内容都称为 light DOM
,而Shadow Root
中的任何内容都称为Shadow DOM
。api
当使用 light DOM
时,可使用 document.querySelector('selector')
选择元素,或者使用 element.querySelector('selector')
选择任何元素的子元素;浏览器
一样,能够经过调用 shadowRoot.querySelector
来选择阴影根的子元素,而 shadowRoot
是对文档片断的引用; 区别在于阴影根的子元素不能从 light DOM
中选择。例如,若是咱们有一个包含 <button>
的阴影根,调用 shadowRoot.querySelector('button')
将返回咱们的按钮,可是不能document's
查询选择器获取该元素,由于它属于不一样的 DocumentOrShadowRoot
实例。markdown
在这方面,shadow DOM
的工做方式有点像 <iframe>
,其中shadow DOM
中的内容与document
的其他部分隔离开来; 然而,当咱们建立 shadow root
时,咱们仍然能够彻底控制页面的这一部分,可是范围仅限于上下文。这就是咱们所说的封装。app
若是您曾经编写太重用相同 id 的组件,或者依赖于 CSS-in-JS 工具或 CSS 命名策略(好比 BEM) ,那么 shadow DOM 有可能改善您的开发人员体验。框架
想象一下这样的场景:ide
<div>
<div id="example">
<!-- Pseudo-code used to designate a shadow root -->
<#shadow-root>
<style> button { background: tomato; color: white; } </style>
<button id="button">This will use the CSS background tomato</button>
</#shadow-root>
</div>
<button id="button">Not tomato</button>
</div>
复制代码
除了 <#shadow-root>
的伪代码(这里使用它来划分 shadow DOM
的边界)以外,其余的 HTML
是彻底有效的。为了在上面的节点上附加一个shadow root
,咱们能够运行下面的代码:
const shadowRoot = document.getElementById('example').attachShadow({ mode: 'open' })
shadowRoot.innerHTML = `<style> button { color: tomato; } </style> <button id="button"> This will use the CSS color tomato <slot></slot> </button>`
复制代码
经过使用 <slot>
元素,影子根还能够包含其余外部节点内容。使用插槽会将用户内容从外部节点 放到阴影根元素的指定位置。
命名恰当的 HTML <template>
元素容许咱们在普通 HTML
流中重用的代码模板,这些模板不会当即显示,但能够在须要的时候使用。
<template id="book-template">
<li><span class="title"></span> — <span class="author"></span></li>
</template>
<ul id="books"></ul>
复制代码
上面的例子不会渲染任何内容,直到脚本使用了模板,实例化了代码并告诉浏览器该如何处理它。
const fragment = document.getElementById('book-template')
const books = [
{ title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
{ title: 'A Farewell to Arms', author: 'Ernest Hemingway' },
{ title: 'Catch 22', author: 'Joseph Heller' },
]
books.forEach((book) => {
// Create an instance of the template content
const instance = document.importNode(fragment.content, true)
// Add relevant content to the template
instance.querySelector('.title').innerHTML = book.title
instance.querySelector('.author').innerHTML = book.author
// Append the instance ot the DOM
document.getElementById('books').appendChild(instance)
})
复制代码
表面上,使用利用模板 API 的服务的用户能够编写任何形状或结构的模板,这些模板能够在之后建立。网站上的另外一个页面可能使用相同的服务,可是模板的结构是这样的:
<template id="book-template">
<li><span class="author"></span>'s classic novel <span class="title"></span></li>
</template>
<ul id="books"></ul>
复制代码
Web Components 规范是一组底层 api,它们将随着开发人员的需求而不断发展和演进。
在下一篇文章中,咱们将更深刻地了解 HTML 模板部分。而后,咱们将继续讨论自定义元素和影子 DOM。最后,咱们将着眼于更高层次的工具,并将其与当今流行的库和框架结合起来,从而总结所有内容。