先上效果預覽: Web Components 首先,什麼是 Web Components ? "MDN" 給出的定義是: Web Components 是一套不同的技術,允許您創建可重用的定製元素(它們的功能封裝在您的代碼之外)並且在您的web應用中使用它們。 ... ... 實現web compo ...
先上效果預覽:
Web Components
首先,什麼是 Web Components ?
MDN 給出的定義是:
Web Components 是一套不同的技術,允許您創建可重用的定製元素(它們的功能封裝在您的代碼之外)並且在您的web應用中使用它們。
... ...
實現web component的基本方法通常如下所示:
- 使用 ECMAScript 2015 類語法創建一個類,來指定web組件的功能(參閱類獲取更多信息)。
- 使用
CustomElementRegistry.define()
方法註冊您的新自定義元素 ,並向其傳遞要定義的元素名稱、指定元素功能的類以及可選的,其所繼承自的元素。- 如果需要的話,使用
Element.attachShadow()
方法將一個 Shadow DOM 附加到自定義元素上。使用通常的 DOM 方法向 Shadow DOM 中添加子元素、事件監聽器等等。- 如果需要的話,使用
<template>
和<slot>
方法定義一個 HTML 模板。再次使用常規 DOM 方法克隆模板並將其附加到您的 Shadow DOM 中。- 在頁面任何您喜歡的位置使用自定義元素,就像使用常規 HTML 元素那樣。
說人話,就是先定義一個類
class MyCompo extends HTMLElement {
constructor() {
super(); // 一定要先調用 super
// 為所欲為
}
}
在裡面實現需要的功能,比如給自己添加子元素和事件監聽器,設置樣式等,就像在寫平常的 JS 代碼一樣。
然後,註冊這個元素:
window.customElements.define('my-compo', MyCompo)
根據 CustomElements v1 標準,自定義元素的名稱必須包含一個橫線。
最後,在 HTML 裡面寫入這個標簽:
<my-compo></my-compo>
標簽必須有結束標簽與之對應,不能使用自閉合標簽。
然後就可以充分享受 CustomElements 帶來的樂趣了,是不是很簡單呢 (誤
通常,Custom Elements 會與 ShadowDOM 結合使用。那什麼是 ShadowDOM 呢?
ShadowDOM
MDN 給出的定義是:
An important aspect of web components is encapsulation — being able to keep the markup structure, style, and behavior hidden and separate from other code on the page so that different parts do not clash, and the code can be kept nice and clean. The Shadow DOM API is a key part of this, providing a way to attach a hidden separate DOM to an element.
大概翻譯一下:
封裝是 Web Components 中重要的一環,可以將元素的 DOM 樹結構、樣式以及行為邏輯與頁面中的其他部分相隔離以避免衝突,並使你的代碼保持整潔。 Shadow DOM API 是其中的關鍵部分,它提供了向元素中插入隱藏 DOM 子樹的方法。
簡言之,Shadow DOM API 可以在任意元素內部插入一個隔離的 DOM 子樹,其中的元素與樣式與外部 DOM 保持隔離,不會影響到外部。所以無需擔心 CSS 代碼相互衝突。
說了這麼多,相容性怎麼樣呢?
抱歉,打擾了(
但我們可以使用 Polyfill ,比如這個 webcomponentsjs ,這裡就不展開介紹了。
我的博客園頁面中已經加入了註入 Polyfill 的代碼,如果你的瀏覽器不能正確載入,那真的改換瀏覽器了 ...
<script>
(function () {
const sd = 'attachShadow' in Element.prototype;
const ce = 'customElements' in window;
if (!sd && !ce) {
document.write('<script src="https://files.cnblogs.com/files/rocket1184/webcomponents-sd-ce.js"><\/script>')
return;
}
!ce && document.write('<script src="https://files.cnblogs.com/files/rocket1184/custom-elements.min.js"><\/script>')
!sd && document.write('<script src="https://files.cnblogs.com/files/rocket1184/shadydom.min.js"><\/script>')
})();
</script>
MelodyPlayer
額,跑題了,今天發文章的目的其實是介紹播放器啊,播放器播放器~~~
首先,播放器支持兩種模式,一種是單曲模式,就像這樣:
預設播放一遍之後停止,也可以點擊右邊第二個按鈕切換到單曲迴圈模式。
然後是列表模式,就像文章一開始時展示的那樣,多了 上一曲 和 下一曲 的按鈕,預設播放列表一遍後停止。也可以選擇列表迴圈、單曲迴圈或是隨機模式。
最右邊的按鈕可以展開/收起歌詞面板。支持一或兩個歌詞同時顯示,還有流暢的滾動動畫。歌詞載入失敗後會有提示。
技術棧與優化
JS 部分使用了 ECMAScript 2015 各種語法,以及 JSX 。但並沒有使用 React ,而是用 babel 自定義 JSX @pragma
,並實現了一個自定義的 createElement
。 Webpack 配置可以參見 這裡 。
CSS 部分使用了 Less ,但並沒有生成獨立的樣式文件,也沒有用 style-loader 。在 Webpack 的配置中,僅使用 less-loader 將 *.less
轉譯為 *.css
,然後使用 css-loader 解析 CSS 中的 url()
部分,併在 JS 代碼中將解析後的 CSS 字元串添加到 ShadowRoot 下。
圖標使用了 Google 的 Material Design Icons ,但並沒有全量引入。我只將需要用到的 10 個圖標提取出來,生成了字體的子集,只有不到 1KB 大小。然後使用 url-loader 將字體轉為 Data URL 並內聯在 CSS 中。關於壓縮字體的方法及原理,請移步我的獨立博客:製作極限壓縮的 Material Icons 圖標字體
經過上述的優化,整個 melody-player.min.js
只有不到 23KB 的大小。
最後,附上 GitHub 鏈接,歡迎 Star ~
GitHub 倉庫: rocka/melody-player
GitHub Demo: MelodyPlayer Demo