狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

都2024年了,做WEB開發的還不知道 Web Components 呢!

admin
2024年3月27日 16:37 本文熱度 691

網絡技術的快速發展,帶來了層出不窮的新概念和框架,尤其是在前端開發領域,新技術的出現如同浪潮般一波接一波,例如 Vue3 和 Vite 的組合。而在這種技術快速更新的環境中,Web Components 作為一項已經存在一段時間的技術,為什么仍然值得我們深入學習和探討呢?

---- 文章的篇幅可能較長,借助目錄效果更好。

Web Components 是由 W3C 推動的標準化技術,它得到了包括 Chrome、Firefox、Safari 和 Edge 在內的主流瀏覽器的廣泛支持。不僅 Vue3 的更新就包括了對 Web Components 的原生支持,現在面試也問 Web Components 話題,尤其是頻頻出現 Shadow DOM

這項技術的魅力在于,它允許開發者創建自定義、可重用的元素,這些元素可以在任何符合標準的 Web 應用中無縫使用,而不受限于特定的框架(React、Vue)。如果你還對 Web Components 比較陌生,那么現在是時候開始了解這項技術了。

Web Components 核心概念

Web Components 是一種瀏覽器原生支持的 Web 組件化技術,它允許開發者創建可重用的自定義元素,并且可以在任何支持 Web Components 的瀏覽器中使用。

image.png

Web Components 包括以下幾個核心概念:

  1. Custom Elements(自定義元素):允許開發者創建新的 HTML 元素,并且可以定義它的行為和樣式。
  2. Shadow DOM(影子 DOM):允許開發者封裝組件的內部結構和樣式,避免全局命名空間的污染。
  3. Templates(模板):允許開發者定義一個可以在多個組件中重用的 HTML 結構。
  4. Slots(插槽):允許開發者創建一個可插入內容的占位符,以便在不同的組件中使用。

今天將圍繞這 4 個核心概念以及相關拓展,通過例子演示重點說一下 Web Components 是如何創建可重用的自定義元素的。

Custom Elements(自定義元素)

Web Components 最大的特性之一就是能將 HTML 封裝成 Custom Elements(自定義元素)。下面我們通過一個簡單的按鈕例子,看下它是怎么實現的。

創建自定義元素

首先,我們需要定義一個自定義元素。這可以通過使用 customElements.define() 方法來實現。在這個例子中,我們將創建一個名為 my-button 的自定義元素。

// main.js
class MyButton extends HTMLElement {
 constructor() {
   super();
   const shadowRoot = this.attachShadow({ mode: 'open' });
   shadowRoot.innerHTML = `
     <style>
       button {
         background-color: #4CAF50;
         border: none;
         color: white;
         text-align: center;
         text-decoration: none;
         display: inline-block;
         font-size: 16px;
         margin: 4px 2px;
         cursor: pointer;
         padding: 10px 24px;
         border-radius: 4px;
       }
     </style>
     <button>Click Me!</button>
   `
;
 }
}
customElements.define('my-button', MyButton);

現在我們已經定義了一個名為 my-button 的自定義元素,我們可以在 HTML 文件中直接使用它。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Web Components Example</title>
</head>
<body>
 <my-button></my-button>

 <script src="./main.js"></script>
</body>
</html>

在這個例子中,我們創建了一個名為 my-button 的自定義元素,并在 HTML 文件中直接使用它。這個自定義元素將渲染為一個綠色的按鈕,上面寫著“Click Me!”。

不止如此,CustomElements 還支持自定義元素行為(如添加點擊事件),也就是說既能封裝 UI 樣式,也是封裝 UI 交互。

const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.querySelector('button').addEventListener('click', () => {
   alert('按鈕被點擊了!');
});

到這里為止,便實現了一個簡單的 Web Components,詳細代碼見CustomElements[1]

生命周期回調方法

Custom Elements 也有一組生命周期回調方法(到這里是不是感覺 Web Component 就像 Vue、React似得,怎么還有生命周期?),這些方法在元素的不同生命周期階段被調用。這些生命周期方法允許你在元素的創建、插入文檔、更新和刪除等時刻執行操作。

以下是自定義元素的一些主要生命周期回調方法:

  1. constructor(): 構造函數,在創建元素實例時調用。適用于執行初始化操作,例如設置初始屬性、添加事件監聽器或創建 Shadow DOM。
  2. connectedCallback(): 當自定義元素被插入到上下文時調用。適用于元素被插入到 DOM 時執行的操作,例如獲取數據、渲染內容或啟動定時器。
  3. disconnectedCallback(): 當自定義元素從文檔中移除時調用。適用于元素從 DOM 中移除時執行的操作,例如移除事件監聽器或停止定時器。
  4. attributeChangedCallback(attributeName, oldValue, newValue): 當自定義元素的屬性被添加、移除或更改時調用。要使用這個回調,你需要在類中定義一個靜態的 observedAttributes 屬性,列出你想要監聽的屬性。

下面是一個簡單的例子,展示了如何在自定義元素中使用這些生命周期方法:

class MyCustomElement extends HTMLElement {
 constructor() {
   super();
   // 初始化操作,例如創建 Shadow DOM
   const shadowRoot = this.attachShadow({ mode: 'open' });
   shadowRoot.innerHTML = '<p>這是一個自定義元素</p>';
 }
 connectedCallback() {
   // 元素被插入到 DOM 時執行的操作
   console.log('Custom element connected to the DOM');
 }
 disconnectedCallback() {
   // 元素從 DOM 中移除時執行的操作
   console.log('Custom element disconnected from the DOM');
 }
 attributeChangedCallback(name, oldValue, newValue) {
   // 監聽的屬性發生變化時執行的操作
   console.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);
 }
 staticget observedAttributes() {
   // 返回一個數組,包含需要監聽的屬性
   return ['my-attribute'];
 }
}
customElements.define('my-custom-element', MyCustomElement);

在 HTML 中使用這個自定義元素:

<my-custom-element my-attribute="value"></my-custom-element>

當 my-custom-element 被插入到 DOM 中時,connectedCallback 會被調用。如果元素被從 DOM 中移除,disconnectedCallback 會被調用。如果元素的 my-attribute 屬性發生變化,attributeChangedCallback 會被調用。

注意:監聽的同時,也記得停止監聽。比如說你可能需要在元素連接到 DOM 時開始監聽事件,但是在元素斷開連接時停止監聽,避免內存泄漏。

Shadow DOM(影子 DOM)

下面我們將繼續探討 Shadow DOM,它是 Web Components 的核心特性之一。

Shadow DOM

Shadow DOM 允許開發者創建一個封閉的 DOM 子樹,這個子樹與主文檔的 DOM 分離,這意味著 Shadow DOM 內部的樣式和結構不會受到外部的影響,也不會影響到外部。

在“Custom Elements(自定義元素)”的例子中,我們已經簡單使用了 Shadow DOM。

1、使用 innerHTML

通過設置 Shadow DOM 的 innerHTML 屬性,可以直接添加一個或多個元素。這種方式適用于從字符串模板快速填充 Shadow DOM。

class MyElementInnerHTML extends HTMLElement {
 constructor() {
   super();
   const shadowRoot = this.attachShadow({ mode: 'open' });
   shadowRoot.innerHTML = `
     <style>
       p { color: black; }
     </style>
     <p>使用 innerHTML</p>
   `
;
 }
}
customElements.define('my-element-inner', MyElementInnerHTML);

2、使用 createElement 和 appendChild

也可以使用 document.createElement 方法創建一個新元素,然后使用 appendChild 方法將其添加到 Shadow DOM 中。

const wrapper = document.createElement('p');
wrapper.textContent = '使用 createElement 和 appendChild';

var style = document.createElement('style');
style.textContent = `
p { color: gray; }
`
;
// 引入外部樣式同樣可以使用 appendChild
// const linkElement = document.createElement('link');
// linkElement.setAttribute('rel', 'stylesheet');
// linkElement.setAttribute('href', 'style.css');
class MyElementAppend extends HTMLElement {
 constructor() {
   super();
   const shadowRoot = this.attachShadow({ mode: 'open' });

   shadowRoot.appendChild(wrapper);
   shadowRoot.appendChild(style);
   // shadowRoot.appendChild(linkElement);
 }
}
customElements.define('my-element-append', MyElementAppend);

3、template 方式

除上面兩種方式外,還可以使用模板元素 (<template>)添加,具體見下方 “Templates(模版)”

Shadow Mode

其中在自定義元素的構造函數中,我們調用了 attachShadow() 方法,并傳入了一個對象 { mode: 'open' }。這里的 mode 屬性決定了 Shadow DOM 的封裝模式,它有兩個可能的值:

  • open:允許外部訪問 Shadow DOM 的 API。
  • closed:不允許外部訪問 Shadow DOM 的 API。

在這個例子中,我們創建了一個 Shadow DOM,并向其中添加了一行文字和相關的樣式。由于 Shadow DOM 的封裝性,這些樣式只會在 my-element 元素內部生效,不會影響到頁面上的其他元素(樣式隔離)。

下面我們更詳細地探討 Shadow DOM 是否允許外部訪問,的兩種封裝模式:open 和 closed

1、Shadow Mode:open 模式

當使用 open 模式創建 Shadow DOM 時,外部腳本可以通過 Element.shadowRoot 屬性訪問 Shadow DOM 的根節點。

這意味著你可以從外部查詢、修改 Shadow DOM 內部的元素和樣式。下面是一個使用 open 模式的例子:

class OpenMyElement extends HTMLElement {
 constructor() {
   super();
   // 創建一個 open 模式的 Shadow DOM
   const shadowRoot = this.attachShadow({ mode: 'open' });
   shadowRoot.innerHTML = `
     <style>
       p { color: red; }
     </style>
     <p>這是一個 open 模式的 Shadow DOM</p>
   `
;
 }
}
customElements.define('open-my-element', OpenMyElement);

// 在外部訪問 Shadow DOM
const element = document.querySelector('open-my-element');
console.log(element.shadowRoot); // 輸出 ShadowRoot 對象

在這個例子中,我們創建了一個自定義元素 open-my-element,它有一個 open 模式的 Shadow DOM。由于模式是 open,我們可以在外部通過 element.shadowRoot 訪問 Shadow DOM 的根節點,并進行進一步的操作,比如添加或刪除子元素,修改樣式等。

image.png

2、Shadow Mode:closed 模式

當使用 closed 模式創建 Shadow DOM 時,外部腳本無法通過 Element.shadowRoot 屬性訪問 Shadow DOM 的根節點。

這意味著 Shadow DOM 內部的元素和樣式對外部是完全隱藏的,無法從外部直接訪問或修改。 下面是一個使用 closed 模式的例子:

class ClosedMyElement extends HTMLElement {
 constructor() {
   super();
   // 創建一個 closed 模式的 Shadow DOM
   const shadowRoot = this.attachShadow({ mode: 'closed' });
   shadowRoot.innerHTML = `
     <style>
       p { color: blue; }
     </style>
     <p>這是一個 closed 模式的 Shadow DOM</p>
   `
;
 }
}
customElements.define('closed-my-element', ClosedMyElement);

// 在外部嘗試訪問 Shadow DOM
const element = document.querySelector('closed-my-element');
console.log(element.shadowRoot); // 輸出 null

在這個例子中,我們創建了一個自定義元素 closed-mode-element,它有一個 closed 模式的 Shadow DOM。由于模式是 closed,當我們嘗試在外部通過 element.shadowRoot 訪問 Shadow DOM 的根節點時,將得到 null

image.png

open 和 closed 模式決定了 Shadow DOM 的封裝程度:

  • open 模式允許外部訪問 Shadow DOM 的 API,這意味著你可以從外部查詢和修改 Shadow DOM 內部的元素和樣式。
  • closed 模式不允許外部訪問 Shadow DOM 的 API,這意味著 Shadow DOM 內部的元素和樣式對外部是完全隱藏的,無法從外部直接訪問或修改。

選擇哪種模式取決于你的具體需求。如果你希望組件的內部結構和樣式完全對外部隱藏,使用 closed 模式是更好的選擇。如果你需要從外部訪問和修改組件的內部結構和樣式,使用 open 模式會更合適。

完整代碼,詳見ShadowDOM[2]

其外,Shadow DOM 還支持更高級的用法,比如可以將 Shadow DOM 分割成多個 Shadow Trees,使用 slots(插槽)來插入內容,以及使用 template(模板)來定義可重用的 HTML 結構。

Slots(插槽)

Slots 是一種特殊類型的元素,它允許你將內容從組件的一個部分傳遞到另一個部分,增加了組件的靈活性。它使得 Web Components 自定義元素,更加的靈活。

基礎使用

例如,我們可以修改 my-button 組件,使其允許用戶自定義按鈕文本:

class MyButton extends HTMLElement {
 constructor() {
   super();
   const shadowRoot = this.attachShadow({ mode: 'open' });
   shadowRoot.innerHTML = `
     <style>
       /* ...樣式代碼保持不變... */
     </style>
     <button>
         <slot>Click Me!</slot>
     </button>
   `
;
 }
}
customElements.define('my-button', MyButton);

現在,當我們在 HTML 中使用 my-button 時,我們可以向其中插入任何內容,它會替換掉 <slot> 標簽:

<my-button>Slots Custom Text</my-button>

image.png

命名插槽

在開發中,我們更多的還會遇到不同情況下,選擇插入的內容,這里就用到了命名插槽,使用起來非常方便。

class MyButtonName extends HTMLElement {
 constructor() {
   super();
   const shadowRoot = this.attachShadow({ mode: 'open' });
   shadowRoot.innerHTML = `
     <style>
       /* ...樣式代碼保持不變... */
     </style>
     <button>
       <slot name="element-name"></slot>
       <slot name="element-age"></slot>
       <slot name="element-email"></slot>
     </button>
   `
;
 }
}
customElements.define('my-button-name', MyButtonName);
<my-button-name>
   <span slot="element-name">element-name</span>
</my-button-name>
<my-button-name>
   <span slot="element-age">element-age</span>
</my-button-name>
<my-button-name>
   <span slot="element-email">element-email</span>
</my-button-name>

image.png

是不是很方便,很靈活!!具體代碼詳見Web Components Slots[3]

Templates(模板)

Templates 允許你定義一個可以在多個組件中重用的 HTML 結構。你可以將模板放在 HTML 文件中的任何位置,并通過 JavaScript 動態地實例化它們:

<my-button></my-button>

<template id="my-button-template">
 <style>
   /* ...樣式代碼保持不變... */
 
</style>
 <button>
     <slot>Click Me!</slot>
 </button>
</template>

在 JavaScript 中,你可以這樣使用模板:

class MyButton extends HTMLElement {
 constructor() {
   super();
   const shadowRoot = this.attachShadow({ mode: 'open' });
   const template = document.getElementById('my-button-template');
   // 使用`cloneNode()` 方法添加了拷貝到 Shadow root 根節點上。
   shadowRoot.appendChild(template.content.cloneNode(true));
 }
}
customElements.define('my-button', MyButton);

image.png

這樣,你就可以在不同的組件中重用同一個模板,從而提高代碼的可維護性和重用性。具體代碼下詳見Web Components Templates[4]

相關拓展

Web Components 兼容性

Web Components 是一組用于構建可復用組件的技術,包括 Custom Elements, Shadow DOM, HTML Templates 等。這些技術的出現,使得開發者能夠更好地組織,去開發復雜的網頁應用。然而,由于這些技術相對較新,不同瀏覽器的支持情況不盡相同,因此兼容性問題也是我們需要重點關注的方向。

Custom Elements

image.png

Shadow DOM

image.png

HTML Templates

image.png

從上面可以看出,現階段市場上大部分的瀏覽器已經都原生支持了 Web Components 的規范標準。但是如果說出現了兼容性問題,我們應該怎么處理?

Polyfills

對于舊版瀏覽器不支持的兼容性情況,可以考慮使用 polyfill 來實現兼容性。Polyfills 是一種代碼注入技術,使得瀏覽器可以支持新的標準 API。對于不支持 Web Components 的瀏覽器,我們可以用 Polyfills 讓這些瀏覽器可以支持 Web Components。

這里我們可以用到 webcomponents.js[5] 庫,它可以實現兼容 Custom Elements、Shadow DOM 和 HTML Templates 標準,讓我們在開發時不必考慮兼容性問題。

npm install @webcomponents/webcomponentsjs
<!-- load webcomponents bundle, which includes all the necessary polyfills -->
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>

<!-- load the element -->
<script type="module" src="my-element.js"></script>

<!-- use the element -->
<my-element></my-element>

具體配置詳情,見polyfills webcomponents[6]

React 與 Vue

相信大家也比較關心 Web Components 與現有框架(如 React、Vue)相比有哪些優勢?以及各自適用場景?

首先,Web Components 是一組 Web 平臺 API,允許開發者創建可重用的自定義元素,而無需依賴于任何特定的框架。與現有的前端框架,Web Components 有以下幾個優勢:

  1. 標準化:Web Components 是基于 Web 標準(如 Custom Elements、Shadow DOM 和 HTML Templates)構建的,這意味著它們得到了瀏覽器廠商的直接支持,而不依賴于任何特定的庫或框架。
  2. 輕量級:Web Components 不需要額外的庫或框架即可工作,這可以減少應用程序的依賴性和大小,特別是在不需要框架其他功能的情況下。
  3. 封裝性:通過 Shadow DOM,Web Components 可以將標記結構、樣式和腳本封裝在一起,避免全局樣式和腳本的沖突,保證了組件的獨立性和重用性。
  4. 易于集成:Web Components 可以與現有的框架(如 React 和 Vue)集成,開發者可以在這些框架中使用 Web Components,或者將現有的框架組件封裝成 Web Components 以供其他項目使用。

然而,Web Components 也有其局限性,例如:

  • 生態系統:與 React 和 Vue 等成熟框架相比,Web Components 的生態系統較小,社區支持和資源可能不如這些框架豐富。
  • 功能限制:Web Components 本身不提供狀態管理、路由等高級功能,這些通常需要額外的庫或框架來實現。
  • 性能:對于復雜的應用程序,一些框架(如 React)通過虛擬 DOM 等技術提供了更高的性能優化,而 Web Components 需要開發者手動優化。

總的來說,Web Components 提供了一種標準化且框架無關的方式來構建組件,適合組件庫的開發。而框架如 React、Vue 則在生態系統支持、開發體驗和數據處理方面有明顯優勢,適合快速開發復雜的應用程序

實際應用案例

  1. Vue3: Vue3 引入了對 Web Components 的原生支持,通過所謂的 “Vue Components”,它允許將 Vue 組件轉換為 Web Components。
  2. MicroApp[7]:基于 Web Components 的一款簡約、高效、功能強大的微前端框架。
  3. Twitter[8]:Twitter 2016 年開始將自己的嵌入式推文   從 iframe 切換成  ShadowDOM,減少了內存消耗、加快了渲染速度,并批量渲染的時候保持絲滑。
  4. svelte + vite 開發 Web Components[9]:通過 svelte + vite 快速搭建 web components 的項目。
  5. 使用 Polymer 構建 Web Components[10]:用于構建 Web Component,它提供了一套工具和 API,能夠更容易地創建自定義元素。

參考資料

  1. **MDN Web Docs - Web Components 入門**[11]
  2. 你不知道的 Web Components - 現狀[12]
  3. 自定義元素 v1 - 可重復使用的網絡組件[13]
  4. Web Components Tutorial for Beginners \[2019\][14]

總結

Web Components 是 W3C 推動的標準化技術,它通過自定義元素的方式,允許開發者在瀏覽器中直接使用。這種技術通過 Shadow DOM 實現了組件化 DOM 隔離和樣式隔離,確保了組件的獨立性和可重用性,這些特性被現有很多借鑒和使用。


該文章在 2024/3/27 16:37:49 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved