先說聲抱歉,本篇和下一篇都是以實做"VanillaJS"版本的web component組件庫為前提。大部分的web component編輯指引都建議使用lit-element之類的函式庫建立組件庫,現在還在使用VanillaJS來建立web component的組件庫幾乎只能說是一種浪漫了?
現代的UI用組件庫不管是跨框架的(bootstrap,tailwindcss,),還是單一框架的(antd.js,mui.js,element-ui),幾乎都有以下二個主要需求。
CSS變數是滿足上面的二個主要需求的最簡單寫法,因為CSS變數是會自動繼承到所有的子節點。也能讓Shadow DOM裡的節點使用
CSS變數都會搭配使用var(),但在使用時建議設定fallback value,畢竟使用者不一定會想設定CSS變數。
.primary-text {
color: var(--primary-color, #00a0e9);
}
關鍵或是常用的參數設定CSS變數還可以(比方說--primary-color),如果要大量客製化,參數的設定會讓人頭皮發麻。
CSSStyleSheet這個物件是用來讓javascript可以生成CSS的樣式表。在Shadow DOM中使用的話,有以下幾個方便的地方。
這個物件意外的很早就在各個瀏覧器中實做完成了,連古老的IE9都能使用(有些語法比較不一樣就是了),我是直到學習web component時才知道有這玩意的存在。
HTML
<body>
<my-div></my-div>
<button id="btn1">style1</button>
<button id="btn2">style2</button>
</body>
javascript
const sheet1 = new CSSStyleSheet();
sheet1.replaceSync('div { width: 100px; height: 100px; border: 1px solid black }');
const sheet2 = new CSSStyleSheet();
class MyDiv extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({mode: 'open'});
const div1 = document.createElement('div');
div1.className = 'div1';
shadow.appendChild(div1);
const div2 = document.createElement('div');
div2.className = 'div2';
shadow.appendChild(div2);
// 可以附加多個sheet
shadow.adoptedStyleSheets = [sheet1, sheet2];
}
}
// customElements.define('my-div', MyDiv)
window.customElements.define('my-div', MyDiv)
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
btn1.addEventListener('click', () => {
// 增加規則,Shadow DOM內的節點也會被影響
sheet2.insertRule('.div1 { background-color: aqua; }');
})
btn2.addEventListener('click', () => {
sheet2.insertRule('.div2 { background-color: red; }');
})
因為和web component沒有直接關係,請直接參考MDN的說明,下面只會列出和web component比較有關的語法
shadow.styleSheets:列出shadow DOM內使用的CSSStyle的列表。
shadow.styleSheets[index].cssRules:列出shadow DOM內使用的某一個CSSStyle內含有的所有CSS規則。
shadow.styleSheets[index].replace(ruleText):把shadow DOM內某一個CSSStyle內含有的所有CSS規則用新的CSS規則全部更換。
shadow.styleSheets[index].insertRule(ruleText):把shadow DOM內某一個CSSStyle新增CSS規則。
shadow.styleSheets[index].deleteRule(index):把shadow DOM內某一個CSSStyle的某一條規則刪除。