本文翻译自: https://css-tricks.com/an-int...
本文首发于公众号:符合预期的CoyPan
前端开发正在以惊人的速度发展。曾经的前端开发,技术栈都是很简单的,现在却愈来愈复杂。这一点从无数的文章、教程和Twitter上就能够看出来。在本文中,我将讨论为何Web Component是一个很好的工具,能够在不使用复杂框架或构建步骤的状况下提供高质量的用户体验,并且不存在过期的风险。在这个由五部分组成的系列的后续文章中,咱们将深刻研究每一个规范。javascript
本系列假设您基本了解HTML、CSS和JavaScript。若是您在其中一个领域感到软弱,不用担忧,构建自定义元素实际上简化了许多前端开发中的复杂性。css
系列文章:html
An Introduction to Web Components (本文)前端
Crafting Reusable HTML Templatesjava
Creating a Custom Element from Scratchweb
Encapsulating Style and Structure with Shadow DOM浏览器
Advanced Tooling for Web Componentsapp
Web Components 由三种技术组成。这三种技术会一块儿使用。框架
上述三种技术组成了Web Components规范。dom
HTML Modules 有可能会成为第四种技术。可是四大浏览器都尚未实现HTML Modules。Chrome团队已经声明将在将来的版本中实现HTML Modules
Web Components 在目前全部的主流浏览中都是可使用的,除了微软的Edge和IE11,可是也有polyfill可使用。
将上述的三种技术称为Web Components在技术上来讲是准确的,Web Components这个术语自己也有一些超载。所以,每种技术均可以独立使用或与其余技术结合使用。换句话说,它们并不相互排斥。
让咱们快速看一下上述三种技术。咱们将在其余文章中,深刻了解他们。
就像名字所显示的那样,custome elements就是HTML元素,好比<div> 、<section>、<article>,可是咱们经过浏览器的API本身给元素命名。自定义元素与标准HTML元素(尖括号中的名称)同样,只是它们中老是有一个破折号,如<news-slider>或<bacon-cheesburger>。更进一步,浏览器厂商们都已经承诺不会再新增带有破折号的内置元素,避免和自定义元素产生冲突。
自定义元素包含本身的语义、行为、标记,而且能够跨框架和浏览器共享。
示例能够参考这里:
https://codepen.io/calebdwill...
在这个例子中,咱们定义了咱们本身的HTML元素<my-component>。不能否认的是,这个元素作的事情并很少,可是这就是最基本的自定义元素构建方法。全部的自定义元素都必须以某种方式上继承HTMLElement,这样才能在浏览器上注册上该元素。
自定义元素不依赖与第三方框架。浏览器厂商们正致力于规范的向后兼容性,不过都保证只要按照规范编写的组件都不会受到API大改的影响。更重要的是,这些自定义元素在当今的主流框架(Angular、React、Vue)中,只须要稍作修改,就能够作到开箱即用。
Shadow DOM是对DOM的一个封装。这使得做者可以有效地将DOM片断彼此隔离开来,包括任何能够用做CSS选择器的东西以及与之关联的样式。一般状况下,document范围内的内容都被称为light DOM,shadow root中的内容被称为shadow DOM。
当咱们使用light DOM的时候,咱们能够经过document.querySelector('selector')来选中某个DOM,或者经过element.querySelector('selector')来获取每一个元素的子元素。一样的,shadow root的子元素能够经过shadowRoot.querySelector来获取,这里的shadowRoot是一个document fragment。不一样的地方是,shadow root的子元素没法在light dom中被选中。例如,若是咱们的shadow root中有一个<button>,使用shadowRoot.querySelector('button')能够获得咱们的button,可是调用document的querySelector就取不到这个button,由于这个button属于不一样的DocumentOrShadowRoot实例。样式选择器也是同样的。
从某种意义上来讲,shadow dom有点像一个iframe,其中的内容与document的其余部分隔开了。不过,当咱们建立一个shadow root的时候,咱们仍然能够彻底控制页面中这部分的内容,只是说须要在必定的做用域下。这就是咱们所说的封装。
若是你曾经写过一个重用相同的id或者依赖CSS-in-JS工具,CSS命名策略(好比BEM)的组件,shadow dom或许提高你的开发体验。
想象一下以下的场景:
<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>的伪代码(没有HTML元素,用来分割shadow的边界),HTML是彻底合法的。为了实现上面的HTML,咱们须要运行下面的代码:
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>`;
shadow root也可使用<slot>元素来从其内部的文档内容中包含内容。使用slot能够把外部文档中的用户内容放到shadow root目录中的指定位置。
示例能够参考这里:
https://codepen.io/calebdwill...
适当命名的HTML<template>元素容许咱们在正常HTML流中消除代码的可重用模板。这些模板不会当即被渲染,但能够在之后使用。
<template id="book-template"> <li><span class="title"></span> — <span class="author"></span></li> </template> <ul id="books"></ul>
上面的例子不会渲染任何的东西,直到咱们使用script操做了这个模板,实例化代码并告诉浏览器如何操做它。
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); });
请注意,此示例建立了一个模板(<template id=“book template”>),而不使用任何其余Web Components技术,再次说明Web Components中的三种技术能够独立使用或共同使用。
表面上,可使用模板API书写一个任意结构的模板,而且在后续的代码中建立这个模板。站点上的另一个页面可能会使用相同的服务,可是使用另外的结构来建立模板:
<template id="book-template"> <li><span class="author"></span>'s classic novel <span class="title"></span></li> </template> <ul id="books"></ul>
能够点击这里查看示例:
https://codepen.io/calebdwill...
随着Web开发愈来愈复杂,像咱们这样的开发者开始将愈来愈多的开发推迟到Web平台自己,而Web平台自己也在不断成熟。Web Components规范是一组低级API,随着开发者的发展,这些API将随着咱们的需求不断增加和发展。