天天看點

Lit 2.x:會讓 Web Component 真正火起來麼?

作者:進階前端進階

大家好,很高興又見面了,我是"進階前端‬進階‬",由我帶着大家一起關注前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關注、點贊、收藏、轉發,您的支援是我不斷創作的動力。

Lit 2.x:會讓 Web Component 真正火起來麼?

今天給大家帶來的主題是Lit ,即一個簡單的庫,用于建構快速、輕量級的 Web Component。話不多說,直接進入正題!

1.什麼是 Lit

Lit 是一個簡單的庫,用于建構快速、輕量級的 Web Component。 Lit 的核心是一個消除樣闆的元件基類,它提供反應式狀态、作用域樣式和一個微小、快速且富有表現力的聲明性模闆系統。

Lit 2.x:會讓 Web Component 真正火起來麼?

Lit 具有以下優勢:

  • 簡單/去樣闆化:Lit 建立在 Web Component 标準之上,添加了反應性、聲明性模闆和一些優秀功能,以減少樣闆檔案并使工作更輕松。 每個 Lit 功能都經過精心設計,并考慮到 Web 平台的發展。
  • 快速地/體積小/即時更新:Lit 的體積約為 5 KB(minified and compressed),有助于保持較小的包體積并縮短加載時間。而且渲染速度非常快,因為 Lit 在更新時隻涉及 UI 的動态部分 ,無需重建虛拟樹并将其與 DOM 進行比較。
  • 可互操作/面向未來:每個 Lit 元件都是原生 Web Component,具有超強的互操作性。 Web Component 可以在任何使用 HTML 的地方工作,可以使用任何架構,也可以不使用架構。 這使得 Lit 成為建構可共享元件、設計系統或可維護、面向未來的網站和應用程式的理想選擇。

除了以上特點外,Lit 的優勢還包括:

  • 标準自定義元素:Lit 元件是标準的自定義元素,是以浏覽器将它們完全視為内置元素。 在手寫的 HTML 或架構代碼中使用它們,從 CMS 或靜态站點建構器輸出它們,甚至在 JavaScript 中建立執行個體
  • 支援範圍樣式(Scoped styles):Lit 預設使用 Shadow DOM 來确定樣式的範圍,進而使得 CSS 選擇器保持簡單,并確定元件的樣式不會影響頁面上的任何其他樣式,也不受其影響。
  • 支援反應性:支援聲明響應式屬性來對元件的 API 和内部狀态進行模組化。 每當反應性屬性(或相應的 HTML 屬性)發生變化時,Lit 元件就會有效地重新渲染。
  • 聲明性模闆:Lit 模闆基于标記的模闆文字,簡單、富有表現力且快速,具有 HTML 标記和内聯的原生 JavaScript 表達式。 無需學習自定義文法,更重要的是無需編譯。

目前 Lit 在 Github 上通過 BSD-3-Clause 協定開源,有超過 15.1k 的 star、0.8k 的 fork、38.1k 的項目依賴量,代碼貢獻者 160+,npm 周平均下載下傳量 845k,是一個妥妥的前端優質開源項目,值得長期關注。

2.Lit 的使用場景

開發者可以使用 Lit 建構幾乎任何類型的 Web UI!

每個 Lit 元件都是标準的 Web 元件。 Web 元件具有互操作性的超強能力,本身受浏覽器的支援,可以在任何 HTML 環境中使用,可以使用任何架構,也可以不依賴架構。

Lit 2.x:會讓 Web Component 真正火起來麼?

這使得 Lit 成為開發可共享元件或設計系統的理想選擇。 Lit 元件可以跨多個應用程式和站點使用,即使這些應用程式和站點建構在各種前端堆棧上。 使用 Lit 元件的站點開發人員不需要編寫甚至不需要檢視任何 Lit 代碼,可以像使用内置 HTML 元素一樣使用這些元件。

Lit 還非常适合用于逐漸增強基本 HTML 網站。 浏覽器将識别标記中的 Lit 元件并自動初始化, 無論站點是手工制作的、通過 CMS 管理的、使用伺服器端架構建構的,還是由 Jekyll 或 Eleventy 等工具生成的。

當然,開發者也可以使用 Lit 元件建構高度互動、功能豐富的應用程式,就像使用 React 或 Vue 等架構一樣。 Lit 的功能和開發人員體驗與這些流行的替代方案相當,但 Lit 通過采用浏覽器的本機元件模型最大限度地減少鎖定、最大限度地提高靈活性并提高可維護性。

總結起來,Lit 非常适用于以下場景:

  • 共享元件:支援可放入任何站點、建構在任何堆棧上的互動式内容。由于浏覽器本身就支援 Web Component,是以 Web Component 是完美的解決方案,而且 Lit 使它們易于建構。
  • 設計系統:設計系統可幫助創造始終如一的卓越品牌體驗,而 Lit 能夠有效解決跨框前端架、跨團隊的諸多問題。
  • 網站和應用程式:使用 Lit 元件逐漸增強靜态站點或建構整個應用程式。 通過采用 Web Component,Lit 最大限度減少了鎖定并提高了可維護性。

3.開始使用 Lit

3.1 安裝 Lit

首先需要使用 npm 安裝 Lit:

npm i lit           

然後導入 JavaScript 或 TypeScript 檔案:

import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators.js";           

當然,Lit 還可以作為預建構的單檔案包提供,進而提高開發工作流程的靈活性:例如,如果開發者更願意下載下傳單個檔案而不是使用 npm 和建構工具。

這些包是沒有依賴關系的标準 JavaScript 子產品 , 任何現代浏覽器都能夠從 <script type="module"> 中導入并運作這些代碼,如下所示:

import {
  LitElement,
  html,
} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";           

3.2 使用 Lit 開發一個 Web Component

下面使用 Lit 開發了一個 Web Component:

import {LitElement, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {play, pause, replay} from './icons.js';
@customElement("my-timer")
// @customElement是類裝飾器工廠将裝飾類定義為自定義元素,即 my-timer
export class MyTimer extends LitElement {
  static styles = css`/* playground-fold */
  :host {
    display: inline-block;
    min-width: 4em;
    text-align: center;
    padding: 0.2em;
    margin: 0.2em 0.1em;
  }
  footer {
    user-select: none;
    font-size: 0.6em;
  }
  @property() duration = 60;
  @state() private end: number | null = null;
  @state() private remaining = 0;
  render() {
    const {remaining, running} = this;
    const min = Math.floor(remaining / 60000);
    const sec = pad(min, Math.floor(remaining / 1000 % 60));
    const hun = pad(true, Math.floor(remaining % 1000 / 10));
    return html`
      ${min ? `${min}:${sec}` : `${sec}.${hun}`}
      <footer>
        ${remaining === 0 ? '' : running ?
          html`<span @click=${this.pause}>${pause}</span>` :
          html`<span @click=${this.start}>${play}</span>`}
        <span @click=${this.reset}>${replay}</span>
      </footer>
    `;
  }
  start() {
    this.end = Date.now() + this.remaining;
    this.tick();
  }
  pause() {
    this.end = null;
  }
  reset() {
    const running = this.running;
    this.remaining = this.duration * 1000;
    this.end = running ? Date.now() + this.remaining : null;
  }
  tick() {
    if (this.running) {
      this.remaining = Math.max(0, this.end! - Date.now());
      requestAnimationFrame(() => this.tick());
    }
  }
  get running() {
    return this.end && this.remaining;
  }
  connectedCallback() {
    super.connectedCallback();
    this.reset();
  }
}           

上面代碼有幾點值得說明:

  • Lit 的主要功能是 LitElement 基類,它是原生 HTMLElement 的便捷且多功能的擴充, 主要功能是:管理元素 properties 和 attribute 并渲染 lit-html 模闆的基本元素類。
  • @property()是一個屬性裝飾器,它建立相應屬性值的反應性屬性。 當設定裝飾屬性時,元素将更新并渲染。 也可以選擇提供 PropertyDeclaration 來配置屬性功能。
  • @state() 聲明一個私有或受保護的響應式屬性,代表元件的公共 API 和/或内部狀态,該屬性在更改時會觸發元素的更新,它不會從相應的屬性中反映出來。
  • 預設情況下,樣式是有範圍(scope)的,使 CSS 選擇器保持簡單,并確定元件的樣式不會污染(或被污染)周圍的上下文。
  • Lit 富有表現力的聲明性模闆(利用 JavaScript 标記模闆文字)可以輕松描述元件的渲染方式。
  • Lit 在普通 JavaScript 表現良好,開發者可以通過使用裝飾器和類型聲明來使用 TypeScript 以獲得更好的人體工程學效果。

聲明了 my-timer 這個 Web Component 後,接着就可以在 HTML 中引入這個 my-timer 來直接使用:

<!doctype html>
<head>
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@1,800&display=swap" rel="stylesheet">
  <script type="module" src="./my-timer.js"></script>
  <style>
    body {
      font-family: 'JetBrains Mono', monospace;
      font-size: 36px;
    }
  </style>
</head>
<body>
  <my-timer duration="7"></my-timer>
  <my-timer duration="60"></my-timer>
  <my-timer duration="300"></my-timer>
</body>           

當然,Lit 還包括:指令(Directives)、Shadow DOM、生命周期(Lifecycle)、上下文(Context)、Lit 服務端渲染(Lit SSR)、前端架構內建等進階用法,這些可以在文末的參考資料中直接使用,本文不再過多展開。

4.本文總結

本文主要和大家介紹 Lit ,即一個簡單的庫,用于建構快速、輕量級的 Web Component。相信通過本文的閱讀,大家對 Lit 會有一個初步的了解。

因為篇幅有限,關于 Lit 的更多用法和特性文章并沒有過多展開,如果有興趣,可以在我的首頁繼續閱讀,同時文末的參考資料提供了大量優秀文檔以供學習。最後,歡迎大家點贊、評論、轉發、收藏,您的支援是我不斷創作的動力。

參考資料

https://github.com/lit/lit

https://lit.dev/tutorials/intro-to-lit/

https://lit.dev/docs/

https://www.npmjs.com/package/lit

https://lit.dev/docs/frameworks/react/

https://coderpad.io/blog/development/web-components-101-framework-comparison/

https://medium.com/front-end-weekly/web-components-lwc-stencil-and-lit-by-numbers-b158efcf82f7

繼續閱讀