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...

相關文章
相關標籤/搜索