web components

web components

组件是前端的发展方向,如今流行的 React angular2.0 Vue 都是组件框架。javascript

谷歌公司因为掌握了 Chrome 浏览器,一直在推进浏览器的原生组件,即Web Components 。相比第三方框架,原生组件简单直接,符合直觉,不用加载任何外部模块,代码量小。目前,它还在不断发展,但已经可用于生产环境。css

Web Components 标准很是重要的一个特性是,它使开发者可以将HTML页面的功能封装为 custom elements(自定义标签)。html

首先咱们须要知道,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...java

HTML Imports

概述
HTML Imports 是一种在 HTMLs 中引用以及复用其余的 HTML 文档的方式。
咱们最多见的引入一个 css 文件的方式是:
<link rel="stylesheet" href="/css/master.css">
Web Components 如今提供多了一个这个:
<link rel="import" href="/components/header.html">
须要服务器环境,能够用nodejs搭一个node

https://segmentfault.com/a/11...web

HTML Templates

概述
这个东西很简单,用过 handlebars 的人都知道有这么一个东西:segmentfault

  1. <script id="template" type="text/x-handlebars-template">
  2. ...
  3. </script>

其余模板引擎也有相似的东西,那么 HTML Templates 即是把这个东西官方标准化,提供了一个 template 标签来存放之后须要可是暂时不渲染的 HTML 代码。
之后能够这么写了:浏览器

  1. <template id="template"> ...
  2. </template>
Shadow DOM

Shadow DOM 好像提出很久了,最本质的需求是须要一个隔离组件代码做用域的东西,例如我组件代码的 CSS 不能影响其余组件之类的。服务器

ShadowDOM-ShadowRoot
ShadowDOM主要解决一个文档中可能须要大量交互的多个DOM树创建和维护各自功能边界的问题

HTML支持的其余一些好比视频、音频甚至一些表单的控件,这些控件有些是由很复杂的界面组成的,其实这些界面也是用HTML+CSS写的
例如<video>
https://www.bilibili.com/vide...
1111111111111.PNG
f12后只能看到一个video的标签,但实际它还有个隐藏的shadowDom
咱们把浏览器里的settings-Elements-show user agent shadow Dom 勾选上之后就能看到shadowDom
22222222.PNG
33333333333.PNG
444444444444.PNG

CSS 相关
由于 Shadow DOM 很大程度上是为了隔离样式做用域而诞生的,主文档中的样式规则不对 Shadow DOM 里的子文档生效,子文档中的样式规则也不影响外部文档。

自定义元素能够给它指定全局样式
可是,组件的样式应该与代码封装在一块儿,只对自定义元素生效,不影响外部的全局样式。因此,能够把样式写在<template>里面。

一个小例子:把card封装成<user-card>标签
效果以下:
555.PNG
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...

相关文章
相关标签/搜索