組件化這個詞 應該你們耳朵都聽起繭巴了 在 Vue
React
Angular
三個大佬 的帶領下 , 咱們前端 是否終於告別了 粘貼複製的 "組件化" 時代css
Antd
ElementUi
這些高質量 且開箱即用 的 ui 庫更是讓組件化開發更上一層樓. 若是不編譯 或者 原生能夠實現所謂的組件化嗎? w3c 給了咱們 web component
的解決方案html
mdn 文檔前端
做爲開發者,咱們都知道盡量多的重用代碼是一個好主意。這對於自定義標記結構來講一般不是那麼容易 — 想一想複雜的HTML(以及相關的樣式和腳本),有時您不得不寫代碼來呈現自定義UI控件,而且若是您不當心的話,屢次使用它們會使您的頁面變得一團糟。git
Web Components旨在解決這些問題 — 它由四項主要技術組成,它們能夠一塊兒使用來建立封裝功能的定製元素,能夠在你喜歡的任何地方重用,沒必要擔憂代碼衝突。github
核心的四大要素web
Custom elements(自定義元素)
:一組JavaScript API,容許您定義custom elements及其行爲,而後能夠在您的用戶界面中按照須要使用它們。canvas
Shadow DOM(影子DOM)
:一組JavaScript API,用於將封裝的「影子」DOM樹附加到元素(與主文檔DOM分開呈現)並控制其關聯的功能。經過這種方式,您能夠保持元素的功能私有,這樣它們就能夠被腳本化和樣式化,而不用擔憂與文檔的其餘部分發生衝突。api
HTML templates(HTML模板)
:<template>
和 <slot>
元素使您能夠編寫不在呈現頁面中顯示的標記模板。而後它們能夠做爲自定義元素結構的基礎被屢次重用。瀏覽器
HTML Imports(HTML導入)
:一旦定義了自定義組件,最簡單的重用它的方法就是使其定義細節保存在一個單獨的文件中,而後使用導入機制將其導入到想要實際使用它的頁面中。HTML 導入就是這樣一種機制,儘管存在爭議 — Mozilla 根本不一樣意這種方法,並打算在未來實現更合適的。bash
瀏覽器爲咱們內置了不少組件 , 好比 最經常使用的
input,button,select, 這也是最屌的 兼容三大框架的 ui 庫 :)
以 一個 範圍選擇條爲例
<input type="range"/>
複製代碼
那麼問題來了 調試器上面只顯示了一個元素 它的拖拽把手(小圓點) 是哪來的呢?
接下來 打開 控制面版 (Settings) => Elements => 勾選 (Show user agent shadow DOM)
能夠清楚的看到 有一些額外的 div 元素 被隱藏掉了 小圓點 和 silder 這些樣式就是從這裏來的 這就是所謂的 shadow DOM
,
在網頁中 咱們能夠寫 一些內置的標記 ,他們有自帶的一些樣式 padding ,margin 之類的
<div/>
<p/>
複製代碼
也能夠寫 自定義的 ,好比
<lijinke>666</lijinke>
複製代碼
仍是能夠被正常解析 只不過沒有任何樣式
認識了 上面兩點, 咱們就能夠 開始動手寫代碼了,咱們以一個卡片 (Card) 組件爲例
<template id="my-card-template">
<div class="my-card">
<div class="title">
<slot name="title">代碼標題</slot>
</div>
<pre>
<slot name="content">代碼內容</slot>
</pre>
</div>
</template>
複製代碼
定義一個 template 模板 再定義兩個 slot 用於佔位 , 能夠理解成 調用組件的時候 裏面的值會被替換,放心 這不是在寫 Vue
這時候 保存 刷新網頁, 大功告成
固然 這是不可能 接下來就是 利用 Vue-loader
new Vue({
el:"#my-card-template"
})
複製代碼
好吧, 這是不可能的 ,這時候頁面時一片空白
template
渲染出來首先 寫一個類
class MyCard extends HTMLElement {
constructor(props) {
super();
}
}
複製代碼
第一步: 而後 拿到 template 裏面的內容 注意這裏 不是 innerHTML,
第二步: 將template 掛載在 shadow DOM 上面 (默認打開)
若是 mode 設爲 false 會沒有樣式
class MyCard extends HTMLElement {
constructor(props) {
super();
const {content:temp} = document.querySelector('#my-card-template')
this.attachShadow({mode: 'open'}).appendChild(temp.cloneNode(true));
}
}
複製代碼
customElements.define('my-card',MyCard)
複製代碼
以後就能夠在 html 裏面寫
<my-card>
<span slot="title">我是代碼標題</span>
<p slot="content">
const a = 1;
console.log(a)
</p>
</my-card>
複製代碼
能夠看到 template 裏面的 元素 變成了 shadow DOM 實現了 和 同樣的 shadow DOM 的效果 , 只是尚未樣式
接下來編寫樣式 寫一點簡單的 style
<template id="my-card-template">
<style>
.my-card {
width: 300px;
height: 300px;
background: #fff;
box-shadow: 1px 2px 10px rgba(0, 0, 0, .3);
margin: 10px
}
.title {
height:40px;
background: #dcdcdc;
line-height: 40px;
text-align: center;
}
pre {
padding: 20px;
}
</style>
<div class="my-card">
<div class="title">
<slot name="title">代碼標題</slot>
</div>
<pre>
<slot name="content">代碼內容</slot>
</pre>
</div>
</template>
複製代碼
說真的 像 Vue
的三段式代碼 哈哈.
Web Component 我也是出於好奇玩了玩 感受 API 很不穩定 ,兼容性不好
好比 導入組件的 方法 隨時存在廢除的可能性
<link type="import" href="./xx.html">
複製代碼
不過這確實是一個新的方向 和 新的可能性 做爲前端 應該瞭解, 最近 w3c 推出來了不少新東西 , --自定義變量, css 版的 canvas api, 叫啥子我忘了, 自定義組件 , 原生模塊加載, 前端的生態 是愈來愈好了, 因此
我仍是用 React
+ Node.js
哈哈