web components
组件是前端的发展方向,现在流行的 React angular2.0 Vue 都是组件框架。
谷歌公司由于掌握了 Chrome 浏览器,一直在推动浏览器的原生组件,即Web Components 。相比第三方框架,原生组件简单直接,符合直觉,不用加载任何外部模块,代码量小。目前,它还在不断发展,但已经可用于生产环境。
Web Components 标准非常重要的一个特性是,它使开发者能够将HTML页面的功能封装为 custom elements(自定义标签)。
首先我们需要知道,Web Components 包括了四个部分:
• Custom Elements
• HTML Imports
• HTML Templates
• Shadow DOM
这四部分有机地组合在一起,才是 Web Components。
可以用自定义的标签来引入组件是前端组件化的基础,在页面引用 HTML 文件和 HTML 模板是用于支撑编写组件视图和组件资源管理,而 Shadow DOM 则是隔离组件间代码的冲突和影响。
Custom Elements
概述
Custom Elements 顾名思义,是提供一种方式让开发者可以自定义 HTML 元素,包括特定的组成,样式和行为。支持 Web Components 标准的浏览器会提供一系列 API 给开发者用于创建自定义的元素,或者扩展现有元素。
https://developer.mozilla.org...
HTML Imports
概述
HTML Imports 是一种在 HTMLs 中引用以及复用其他的 HTML 文档的方式。
我们最常见的引入一个 css 文件的方式是:
<link rel="stylesheet" href="/css/master.css">
Web Components 现在提供多了一个这个:
<link rel="import" href="/components/header.html">
需要服务器环境,可以用nodejs搭一个
https://segmentfault.com/a/11...
HTML Templates
概述
这个东西很简单,用过 handlebars 的人都知道有这么一个东西:
- <script id="template" type="text/x-handlebars-template">
- ...
- </script>
其他模板引擎也有类似的东西,那么 HTML Templates 便是把这个东西官方标准化,提供了一个 template 标签来存放以后需要但是暂时不渲染的 HTML 代码。
以后可以这么写了:
- <template id="template"> ...
- </template>
Shadow DOM
Shadow DOM 好像提出好久了,最本质的需求是需要一个隔离组件代码作用域的东西,例如我组件代码的 CSS 不能影响其他组件之类的。
ShadowDOM-ShadowRoot
ShadowDOM主要解决一个文档中可能需要大量交互的多个DOM树建立和维护各自功能边界的问题
HTML支持的其他一些比如视频、音频甚至一些表单的控件,这些控件有些是由很复杂的界面组成的,其实这些界面也是用HTML+CSS写的
例如<video>
https://www.bilibili.com/vide...
f12后只能看到一个video的标签,但实际它还有个隐藏的shadowDom
我们把浏览器里的settings-Elements-show user agent shadow Dom 勾选上以后就能看到shadowDom
CSS 相关
因为 Shadow DOM 很大程度上是为了隔离样式作用域而诞生的,主文档中的样式规则不对 Shadow DOM 里的子文档生效,子文档中的样式规则也不影响外部文档。
自定义元素可以给它指定全局样式
但是,组件的样式应该与代码封装在一起,只对自定义元素生效,不影响外部的全局样式。所以,可以把样式写在<template>里面。
一个小例子:把card封装成<user-card>标签
效果如下:
card.html
<!DOCTYPE html\>
<html\>
<head\>
<meta charset\="utf-8" />
<meta name\="viewport" content\="width=device-width" />
<title\>web Components</title\>
<link rel\="stylesheet" type\="text/css" href\="a.css" />
</head\>
<body\>
<user-card
image\="https://s0.2mdn.net/simgad/320245132277053394?sqp=-oaymwEOCKwCEPoBIAFIZFABWAE&rs=AOga4qmxkPL\_xXMXJ0ZrdWUAw31Jff3bmw"
name\="User Name"
email\="yourmail@some-email.com"
\>
</user-card\>
<user-card
image\="component.PNG"
name\="小明"
email\="yourmail@some-email.com"
\>
<span slot\="my-text"\>slot!</span\>
</user-card\>
<template id\="userCardTemplate"\>
<style\>
:host {
display: flex;
align-items: center;
width: 450px;
height: 180px;
background-color: #d4d4d4;
border: 1px solid #d5d5d5;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
border-radius: 3px;
overflow: hidden;
padding: 10px;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
margin-bottom: 10px;
}
.image {
flex: 0 0 auto;
width: 160px;
height: 160px;
vertical-align: middle;
border-radius: 5px;
}
.container {
box-sizing: border-box;
padding: 20px;
height: 160px;
}
.container > .name {
font-size: 20px;
font-weight: 600;
line-height: 1;
margin: 0;
margin-bottom: 5px;
}
.container > .email {
font-size: 12px;
opacity: 0.75;
line-height: 1;
margin: 0;
margin-bottom: 15px;
}
.container > .button {
padding: 10px 25px;
font-size: 12px;
border-radius: 5px;
text-transform: uppercase;
}
</style\>
<img class\="image" />
<div class\="container"\>
<p class\="name"\></p\>
<p class\="email"\></p\>
<button class\="button"\>Follow John</button\>
</div\>
<div\><slot name\="my-text"\></slot\></div\>
</template\>
</body\>
<script type\="text/javascript" src\="./card.js"\></script\>
</html\>
card.js
class UserCard extends HTMLElement {
constructor() {
super();
var shadow \= this.attachShadow({ mode: "open" });
var templateElem \= document.getElementById("userCardTemplate");
var content \= templateElem.content.cloneNode(true);
content
.querySelector("img")
.setAttribute("src", this.getAttribute("image"));
content.querySelector(".container>.name").innerText \= this.getAttribute(
"name"
);
content.querySelector(".container>.email").innerText \= this.getAttribute(
"email"
);
shadow.appendChild(content);
console.log(this.shadowRoot);
}
}
window.customElements.define("user-card", UserCard);
参考文章:http://www.ruanyifeng.com/blo...
参考文章:
https://juejin.im/post/57c40f...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。