探索Web Components

来源:https://www.cnblogs.com/Amd794/p/18250595
-Advertisement-
Play Games

這篇文章介紹了Web Components技術,它允許開發者創建可復用、封裝良好的自定義HTML元素,並直接在瀏覽器中運行,無需依賴外部庫。通過組合HTML模板、Shadow DOM、自定義元素和HTML imports,Web Components增強了原生DOM的功能,提高了組件化開發的封裝性和... ...



title: 探索Web Components
date: 2024/6/16
updated: 2024/6/16
author: cmdragon

excerpt:
這篇文章介紹了Web Components技術,它允許開發者創建可復用、封裝良好的自定義HTML元素,並直接在瀏覽器中運行,無需依賴外部庫。通過組合HTML模板、Shadow DOM、自定義元素和HTML imports,Web Components增強了原生DOM的功能,提高了組件化開發的封裝性和可維護性,同時支持組件的生命周期管理和高級設計模式,有利於提升網頁應用的性能和開發效率。

categories:

  • 前端開發

tags:

  • Web Components
  • 原生DOM
  • 封裝性
  • 組件化
  • 生命周期
  • 高級設計
  • 性能優化

image

image

掃碼關註或者微信搜一搜:編程智域 前端至全棧交流與成長

第1章:引言

Web Components的起源與發展

Web Components是一種基於Web標準的新興技術,旨在解決Web應用程式開發中的可重用組件化問題。Web
Components的核心思想是,將HTML、CSS和JavaScript結合起來,實現可重用、可組合和可封裝的組件。

Web Components的起源可以追溯到2011年,由W3C(萬維網聯盟)提出的一個名為Web Components Specifications(Web
Components規範)的項目。該項目包括四個主要模塊:

  1. Templates and Slots(模板和插槽):提供一種在HTML中聲明模板的方式,併在組件中使用插槽來實現內容分發。
  2. Shadow DOM(影子DOM):提供一種在組件內部創建獨立的DOM樹,與外部DOM樹隔離開來,實現樣式和內容的封裝。
  3. Custom Elements(自定義元素):提供一種在HTML中定義和註冊新元素的方式,擴展HTML標準元素集。
  4. Decorators(裝飾器):提供一種在組件生命周期中添加額外功能的方式,如屬性觀察器、事件監聽器和生命周期回調。

為什麼選擇Web Components

Web Components具有以下優點:

  • 可重用性:組件可以在不同的項目中重用,提高開發效率和一致性。
  • 可組合性:組件可以嵌套和組合,構建更加複雜的UI。
  • 可封裝性:組件可以在內部實現細節上進行隔離,提高可維護性和可測試性。
  • 與現有Web技術的相容性:Web Components基於Web標準,與HTML、CSS和JavaScript高度相容。

第2章:基礎知識

Web Components概述

Web Components是一系列不同的技術,允許你創建可重用的自定義元素,並且包含了自定義的樣式和行為。這些自定義元素可以像標準HTML元素一樣使用,並且可以在任何地方重用。Web
Components主要由以下三個技術組成:

  1. Custom Elements(自定義元素):允許你定義新的HTML元素,這些元素可以包含自己的HTML結構、CSS樣式和JavaScript行為。
  2. Shadow DOM(影子DOM):提供了一種封裝方式,使得自定義元素可以擁有自己的DOM樹,與頁面的其他部分隔離開來,防止樣式衝突。
  3. HTML Templates(HTML模板):提供了一種聲明性的方式來定義HTML結構,可以在運行時插入到文檔中。
  4. HTML Imports(HTML導入):允許你導入HTML文檔作為模塊,雖然這個特性已經被廢棄,但它的理念被其他模塊化方案所繼承。

HTML、CSS和JavaScript基礎知識

在深入Web Components之前,你需要具備一定的HTML、CSS和JavaScript基礎知識。以下是這些技術的簡要概述:

  • HTML:超文本標記語言,用於創建網頁的結構和內容。
  • CSS:層疊樣式表,用於設置網頁元素的樣式,如顏色、字體和佈局。
  • JavaScript:一種編程語言,用於實現網頁的交互性和動態內容。

Shadow DOM和模板模式

Shadow DOM

Shadow DOM是Web
Components的核心技術之一,它允許你將一個隱藏的、獨立的DOM樹附加到一個元素上。這個DOM樹被稱為“影子DOM”,它與主DOM樹(即頁面上的其他元素)是隔離的。這意味著影子DOM內的樣式和行為不會影響到頁面上的其他元素,反之亦然。這種隔離性使得Web
Components能夠封裝自己的樣式和行為,而不必擔心與其他元素的衝突。

模板模式

模板模式是Web
Components中用於創建自定義元素的一種方式。它允許你定義一個HTML模板,這個模板包含了自定義元素的HTML結構。然後,你可以使用JavaScript來實例化這個模板,並將其附加到DOM中。模板模式通常與Shadow
DOM結合使用,以實現自定義元素的封裝和樣式隔離。

通過結合使用Shadow DOM和模板模式,你可以創建出功能強大、可重用的Web Components,這些組件可以在不同的項目中重覆使用,並且能夠保持自己的樣式和行為。

第3章:基礎組件開發

template元素和slot的使用

template元素在Web Components中扮演了重要角色,它允許你定義組件的結構和內容。template
標簽內可以包含HTML結構,這些結構會被覆制到每個組件實例中。slot
元素則用於定義組件內部可以接收內容的地方,外部可以將內容插入到這些slot中,實現了組件的可擴展性。標準中文電碼查詢 | 一個覆蓋廣泛主題工具的高效線上平臺 (cmdragon.cn)

例如:

<template>
  <div>
    <slot name="header">Default Header</slot>
    <p>Content goes here</p>
    <slot name="footer">Default Footer</slot>
  </div>
</template>

在這個例子中,headerfooter是slot,外部可以傳遞自定義內容替換它們。

custom-element定義與註冊

custom-element是Web Components的核心,用於創建自定義的HTML元素。定義一個custom-element通常需要以下步驟:

  1. 使用<custom-element>標簽定義元素:

    <custom-element name="my-component"></custom-element>
    
    
  2. 實現connectedCallback和可能的其他生命周期方法,如disconnectedCallbackattributeChangedCallback等:

    class MyComponent extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
      }
    
      connectedCallback() {
        // 在這裡添加組件的初始化代碼
      }
    
      // 其他生命周期方法...
    }
    
    customElements.define("my-component", MyComponent);
    
    
  3. connectedCallback中,將自定義元素的shadowRoot(暗影根)添加到模板中:

    connectedCallback() {
      this.shadowRoot.appendChild(this.templateContent);
    }
    
    // 假設templateContent是template元素的內容
    const templateContent = document.querySelector('template');
    
    

style和link元素在組件中的應用

style元素用於定義組件的樣式,通常放在<custom-element>標簽內部,或作為<style>標簽的外部鏈接(<link rel="stylesheet">
)。外部樣式可以通過import導入到組件內部,這樣可以保持樣式和組件的封裝。

<!-- 內部樣式 -->
<style>
  /* ... */
</style>

<!-- 外部鏈接 -->
<link rel="stylesheet" href="styles.css">

在組件內部,可以使用this.shadowRoot來訪問和操作樣式。例如,添加樣式到組件的暗影根:

class MyComponent extends HTMLElement {
  connectedCallback() {
    this.shadowRoot.appendChild(this.styleElement);
  }

  // ...
  constructor() {
    super();
    this.styleElement = document.createElement('style');
    this.styleElement.textContent = `
      /* ... */
    `;
  }
}

這樣,外部樣式可以影響到組件的渲染,同時保持了組件的封裝性。

第4章:原生組件與Web Components的對比

原生DOM元素的特性

原生DOM元素是HTML5中直接提供的,它們具有以下特性:

  1. 簡單易用:直接操作DOM元素,API直觀,易於學習和使用。
  2. 廣泛支持:所有現代瀏覽器都內置了對DOM的支持。
  3. 性能:對於簡單的操作,DOM操作通常很快,但複雜操作可能導致性能問題,特別是當涉及到大量元素時。
  4. 事件處理:DOM提供了豐富的事件模型,可以直接監聽和響應元素的事件。
  5. 樣式控制:可以直接通過style屬性或者CSS類來控制元素的樣式。

Web Components的優勢和局限性

優勢

  • 封裝性:Web Components提供了一種將HTML、CSS和JavaScript封裝在一起的方式,提高了代碼的復用性和維護性。
  • 組件化:組件可以獨立於頁面,可以被多個頁面復用,減少了代碼冗餘。
  • 自定義元素:可以創建自定義的HTML元素,擴展HTML元素庫。
  • 數據綁定:通過<template><slot>,可以實現數據驅動的組件結構。

局限性

  • 學習曲線:Web Components的API和概念可能對初學者來說較難理解和掌握。
  • 瀏覽器支持:雖然大部分現代瀏覽器支持,但一些舊版本瀏覽器可能不支持,需要使用polyfills或polymer庫來彌補。
  • 性能:對於複雜的組件,如果處理不當,可能會有性能問題,尤其是在處理大量數據時。
  • 工具鏈:雖然有工具如Web Components Workbox等來優化,但整體工具鏈相比React、Vue等庫可能不夠成熟。

相容性問題與解決方案

  • 瀏覽器相容性:使用@webcomponents/webcomponentsjs庫或者polyfills(如custom-elements-es5-adapter
    )來提供向後相容性,確保在不支持Web Components的瀏覽器中運行。
  • polyfills:對於一些新特性(如Shadow DOM、HTML Templates等),可以使用polyfills來提供支持。
  • Babel和TypeScript:使用這些工具可以將新特性轉換為舊版本瀏覽器可以理解的代碼。
  • 測試:確保在各種瀏覽器和版本上進行充分的測試,確保組件的相容性。

總的來說,Web Components提供了一種更現代、更模塊化的開發方式,但開發者需要在相容性、學習成本和工具成熟度之間權衡。

第5章:自定義元素API

自定義元素API:生命周期方法

在Web Components中,自定義元素有以下幾個關鍵的生命周期方法:

  1. createdCallback: 當元素被創建(但可能尚未插入到文檔中)時調用。這是初始化元素內部狀態和處理數據的好時機。
class MyCustomElement extends HTMLElement {
  createdCallback() {
    // 初始化元素內部狀態
  }
}

  1. attachedCallback: 當元素被插入到文檔中時調用。這時可以綁定事件和處理DOM操作。
attachedCallback() {
  this.addEventListener('click', this.handleClick);
}

  1. detachedCallback: 當元素從文檔中移除時調用,可以在這裡清理資源。
  2. attributeChangedCallback: 當元素的屬性被修改時調用,可以更新內部狀態。
attributeChangedCallback(name, oldValue, newValue) {
  // 更新屬性值
}

  1. connectedCallback: 在元素被連接到DOM樹中(可能是通過<slot>插入)時調用。

屬性綁定和事件處理

  • 屬性綁定:可以使用<template>元素的<slot><slot-scope>來實現數據綁定,或者使用this.set方法來設置和監聽屬性。
this.set('myProperty', newValue);

  • 事件處理:通過addEventListener方法添加事件監聽器,事件處理函數通常在this上下文中。
addEventListener('click', (event) => {
  // 處理點擊事件
});

與外部數據交互

  • 數據綁定:可以使用<template><slot>來綁定外部數據,或者通過@property裝飾器聲明響應式屬性。
@property({ type: String, reflect: true })
myData;

  • 事件通信:自定義元素可以通過customEvent來觸發自定義事件,外部可以通過addEventListener監聽這些事件。
this.dispatchEvent(new CustomEvent('myCustomEvent', { detail: data }));

  • 數據交互API:使用fetchXMLHttpRequest或Web API(如localStorageIndexedDB)來獲取和存儲數據。

第6章:高級組件設計

高階組件(Higher-Order Components, HOCs)

高階組件(HOCs)是React中用於重用組件邏輯的高級技術。HOC是一個函數,它接受一個組件並返回一個新的組件。HOC可以用來封裝組件,使其更易於重用和測試。

示例代碼:

import React from 'react';

// 定義一個HOC
function withSubscription(WrappedComponent, selectData) {
  // ...並返回一個新組件...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ...那數據源...並訂閱變化...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ...並將新的數據傳遞給被包裝的組件!
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  }
}

集成狀態管理(如Redux或Vue.js)

狀態管理庫(如Redux)可以幫助管理大型應用程式的狀態,使其更易於維護和測試。Redux是一個可預測的狀態容器,用於JavaScript應用。

示例代碼:

import { createStore } from 'redux';

// 創建一個reducer
function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([action.text]);
    default:
      return state;
  }
}

// 創建store
let store = createStore(todos);

// 添加一個todo
store.dispatch({
  type: 'ADD_TODO',
  text: 'Read the docs'
});

// 列印state
console.log(store.getState());

使用Shadow DOM實現封裝和樣式隔離

Shadow DOM提供了一種封裝Web組件的方式,可以隔離樣式和行為,防止與其他組件衝突。

示例代碼:

class MyElement extends HTMLElement {
  constructor() {
    super();
    // 創建一個shadow root
    this.attachShadow({ mode: 'open' });
    // 添加一些內容
    this.shadowRoot.innerHTML = `<h1>Hello, World!</h1>`;
  }
}

// 定義custom element
customElements.define('my-element', MyElement);

通過以上方法,可以設計出更高級、更易於維護和測試的組件

第7章:復用與模塊化

元素的rel="import"和模塊導入

HTML Imports是HTML和JavaScript的一種模塊格式,允許在HTML文檔中導入外部資源。可以使用元素的rel="import"屬性來導入模塊。

示例代碼:

<head>
  <link rel="import" href="my-module.html">
</head>
<body>
  <my-element></my-element>
</body>

Web Components庫和框架(如Polymer、lit-element等)

Web Components是一種模塊化的方法,用於構建可重用和可組合的UI組件。可以使用各種Web Components庫和框架來簡化開發過程。

示例代碼:

// Polymer
import { PolymerElement, html } from '@polymer/polymer';

class MyElement extends PolymerElement {
  static get template() {
    return html`
      <div>Hello, World!</div>
    `;
  }
}

customElements.define('my-element', MyElement);

// lit-element
import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`
      <div>Hello, World!</div>
    `;
  }
}

customElements.define('my-element', MyElement);

Web Components的模塊化最佳實踐

為了確保Web Components的可重用性和可維護性,需要遵循一些最佳實踐。

  1. 組件應該是可重用的:組件應該是獨立的、可重用的,並且不應該依賴於特定的應用程式狀態。
  2. 組件應該是可組合的:組件應該可以與其他組件組合在一起,以創建更大的組件。
  3. 組件應該是可測試的:組件應該是可測試的,可以通過單元測試和集成測試來驗證其功能。
  4. 組件應該是可維護的:組件應該易於理解和維護,並且應該遵循一致的編碼風格和架構。
  5. 組件應該是可訪問的:組件應該遵循可訪問性的最佳實踐,以確保所有用戶都可以使用它們。

通過遵循這些最佳實踐,可以確保Web Components的可重用性和可維護性,並使得應用程式更加模塊化和可擴展。

第8章:現代Web開發中的Web Components

Web Components與現代Web框架的集成

現代Web框架(如Angular、React、Vue)雖然各自有其獨特的組件系統,但它們也支持與Web Components的集成,以利用Web
Components的可重用性和模塊化優勢。以下是一些集成方式:

  • Angular: Angular通過ng-content@Input@Output等特性,可以方便地使用Web Components。可以將Web
    Components作為Angular組件的一部分,或者在Angular應用中作為自定義元素使用。
  • React: React通過forwardRefuseRef等API,可以與自定義元素(Custom Elements)配合使用。通過React.forwardRef將Web
    Components包裝成React組件,可以在React應用中直接使用。
  • Vue: Vue通過v-bindv-on等指令,可以與自定義元素或使用Vue.extend創建的組件一起工作。Vue的Composition API也可以與Web
    Components無縫集成。

Web Components在服務端渲染(SSR)中的應用

服務端渲染(SSR)是現代Web開發中的一種策略,它允許在伺服器端生成完整的HTML,然後發送到客戶端,提高首屏載入速度。對於Web
Components,SSR需要特別處理,因為它們依賴於瀏覽器環境來創建和渲染。

  • 使用伺服器端庫:一些庫(如@webcomponents/web-component-server)提供了服務端渲染Web
    Components的能力,它允許在伺服器上創建虛擬DOM,然後在客戶端上進行渲染。
  • 預渲染:在客戶端首次渲染時,可以將組件的HTML結構和數據一起發送到客戶端,然後在客戶端通過JavaScript初始化這些組件。
  • 狀態管理:確保在伺服器端和客戶端之間同步狀態,因為Web Components可能依賴於組件內部的狀態。

在SSR中使用Web Components時,需要考慮到瀏覽器環境和伺服器環境的差異,確保組件可以在兩種環境下正確工作。同時,由於Web
Components的模塊化特性,它們通常更容易適應SSR的場景。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 轉載自東華果汁哥 Apache DophinScheduler 運行一段時間後,實例調度日誌越來越多,需要定期清理。 SQL 錯誤 [1701] [42000]: Cannot truncate a table referenced in a foreign key constraint (`dol ...
  • 本文提供了利用數據觸發Feishu Webhook的具體操作指南,包括Webhook的設置以及編寫觸發代碼的方法,為讀者提供了實踐參考,希望能幫助解決你目前遇到的問題。 描述 用於使用數據觸發 Feishu Webhook。 例如,如果來自上游的數據是 [age: 12, name: tyrantl ...
  • 目錄一、目的二、環境三、相關概念3.1 屏幕尺寸(screen size)3.2 屏幕解析度(Resolution)3.3 像素(pixel)3.4 ppi3.5 dpi3.6 dp/dip3.7 sp四、Q&A4.1 為啥dpi = 160?4.2 為啥Android要引入dp概念?五、代碼倉庫地 ...
  • 目錄效果圖思路具體實現步驟一:ItemView頂部偏移步驟二:繪製圓和線條註意:下標的獲取流程類的繪製總結 效果圖 可控制是否繪製在中間 控制繪製的線條是否為虛線 控制第一條數據圓頂部線條和最後一條數據圓底部線條是否繪製 除了gif圖片展示的屬性,還可以控制圓的大小顏色、圓是否有上和左偏移、線條顏色 ...
  • ‍ 寫在開頭 點贊 + 收藏 學會 在項目中我們可能會遇到當滑鼠在某個區域內,我們希望滾動滑鼠裡面的內容可以橫向滾動; 比如我們一些常見的後臺狀態欄: 那這種該怎麼寫?請看慄子 代碼如下: <template> <div> <div class="top"> <div class ...
  • 摘要:本文闡述了Nuxt.js作為基於Vue.js的伺服器端渲染框架,其在提升Web開發效率、確保代碼質量和優化應用性能方面的核心價值。通過詳盡的安裝步驟、配置說明、常見問題解決策略及進階部署方法,為開發者搭建和部署Nuxt.js項目提供了全方位指導。 ...
  • JS中有一些操作可以動態地執行JS代碼,並修改或新建詞法作用域,這種操作雖然帶來了更多的靈活性,但是會嚴重地影響到性能。 ...
  • 1. 不使用臨時變數來交換變數的值 2. 對象解構,讓數據訪問更便捷 3. 淺克隆對象 4. 合併對象 5. 清理數組 6. 將 NodeList 轉換為數組 7. 檢查數組是否滿足指定條件 8. 將文本複製到剪貼板 9. 刪除數組重覆項 10. 取兩個數組的交集 11. 求數組元素的總和 12. ... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...