Web Components 系列(八)—— 自定義元件的樣式設定

程式設計三昧發表於2022-02-15

樣式設定.001

前言

透過前面的學習,對自定義元件的相關概念和知識點也有了一定了解,今天我們就來學習一下給自定義元素及其子元素設定樣式的幾種方法。

直接給自定義標籤新增樣式

index.html:

<style>
    my-card{
        display: block;
        margin: 20px;
        width: 200px;
        height: 200px;
        border: 3px solid #000;
    }
</style>
<my-card></my-card>
<script src="./index.js"></script>

index.js:

class MyCard extends HTMLElement {
    constructor() {
        super();
        this.shadow = this.attachShadow({ mode: "open" });
    }
}

window.customElements.define("my-card", MyCard);

結果樣式生效:

image-20220215171224559

需要注意的是:繼承自 HTMLElement 的自定義元素,其 style.display 預設為 inline。

由以上結果可以推論出:

  1. 給自定義元素新增 class,然後透過 class 名稱設定樣式可以生效;
  2. 給自定義元素新增行內樣式,可以生效;
  3. 在自定義元素建構函式中給 this 新增樣式,可以生效。

給自定義元素內部子元素設定樣式

在主 DOM 透過類名設定

在 style 標籤中增加如下樣式:

<style>
    my-card {
        display: block;
        margin: 20px;
        width: 200px;
        height: 200px;
        border: 3px solid #000;
    }
    .card-header {
        padding: 10px;
        font-weight: bold;
        background-color: yellow;
    }
</style>
<my-card></my-card>

<script>
    class MyCard extends HTMLElement {
        constructor () {
            super();
            this.shadow = this.attachShadow({mode: "open"});

            let headerEle = document.createElement("div");
            headerEle.className = "card-header";
            headerEle.innerText = "My Card";
            this.shadow.appendChild(headerEle);
        }
    }
    window.customElements.define("my-card", MyCard);
</script>

結果:不生效。

透過前面的學習,我們知道:自定義元素內部實際上是一個 Shadow DOM,它和主 DOM 是相互隔離的,所以,主 DOM 中的樣式是影響不到 Shadow DOM 的。

使用 JS 給 Shadow DOM 增加 style 標籤

這裡分為兩種場景:在主 DOM 使用 JS 、在 Custom Elements 建構函式中使用 JS。

第一種:在主 DOM 使用 JS 給 Shadow DOM 增加 style 標籤:

<style>
    my-card {
        display: block;
        margin: 20px;
        width: 200px;
        height: 200px;
        border: 3px solid #000;
    }
</style>
<my-card>
</my-card>

<script>
    class MyCard extends HTMLElement {
        constructor () {
            super();
            this.shadow = this.attachShadow({mode: "open"});

            let headerEle = document.createElement("div");
            headerEle.className = "card-header";
            headerEle.innerText = "My Card";
            this.shadow.appendChild(headerEle);
        }
    }
    window.customElements.define("my-card", MyCard);
    // 給 Shadow DOM 增加 style 標籤
    let styleEle = document.createElement("style");
    styleEle.textContent = `
        .card-header{
            padding:10px;
            background-color: yellow;
            font-size: 16px;
            font-weight: bold;
        }
    `;
    document.querySelector("my-card").shadowRoot.appendChild(styleEle);
</script>

效果如下:

image-20220215165202693

第二種:在 Custom Elements 建構函式中使用 JS 增加 style 標籤:

<style>
    my-card {
        display: block;
        margin: 20px;
        width: 200px;
        height: 200px;
        border: 3px solid #000;
    }
</style>
<my-card>
</my-card>

<script>
    class MyCard extends HTMLElement {
        constructor () {
            super();
            this.shadow = this.attachShadow({mode: "open"});
            let styleEle = document.createElement("style");
            styleEle.textContent = `
                .card-header{
                    padding:10px;
                    background-color: yellow;
                    font-size: 16px;
                    font-weight: bold;
                }
            `;
            this.shadow.appendChild(styleEle);


            let headerEle = document.createElement("div");
            headerEle.className = "card-header";
            headerEle.innerText = "My Card";
            this.shadow.appendChild(headerEle);
        }
    }
    window.customElements.define("my-card", MyCard);
</script>

效果如下:

image-20220215164622194

就以上兩種方式來說,第二種更符合元件化的特徵,並且使用第一種方式時要注意,如果將新增 style 標籤的程式碼放在定義 Custom Elements 之前會報錯(找不到自定義元素)。

引入 CSS 檔案

這裡使用 JS 建立 link 標籤,然後引入 CSS 檔案給自定義元素內部的子元素設定樣式,程式碼如下:

<style>
    my-card {
        display: block;
        margin: 20px;
        width: 200px;
        height: 200px;
        border: 3px solid #000;
    }
</style>
<my-card>
</my-card>

<script>
    class MyCard extends HTMLElement {
        constructor () {
            super();
            this.shadow = this.attachShadow({mode: "open"});
            let linkEle = document.createElement("link");
            linkEle.rel = "stylesheet";
            linkEle.href = "./my_card.css";
            this.shadow.appendChild(linkEle);


            let headerEle = document.createElement("div");
            headerEle.className = "card-header";
            headerEle.innerText = "My Card";
            this.shadow.appendChild(headerEle);
        }
    }
    window.customElements.define("my-card", MyCard);
</script>

my_card.css 程式碼如下:

.card-header{
    padding:10px;
    background-color: yellow;
    font-size: 16px;
    font-weight: bold;
}

效果如下:

image-20220215165930769

當然,這裡也可以在主 DOM 中使用 JS 給 Shadow DOM 引入 CSS 檔案,但是,這樣做不符合元件化的特徵,所以略過。

結束語

以上就是給自定義元素及其子元素進行樣式設定的基本方法總結。

~

~ 本文完,感謝閱讀!

~

學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!

大家好,我是〖程式設計三昧〗的作者 隱逸王,我的公眾號是『程式設計三昧』,歡迎關注,希望大家多多指教!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章