在前面的幾篇中,已經把 Lit 的原理層拉出來溜了一圈:

  • 它為什麼不需要 Virtual DOM
  • lit-html 如何通過 Part 精確更新 DOM
  • 響應式系統為什麼極度剋制
  • 生命週期為什麼貼近瀏覽器模型
  • 為什麼幾乎沒有狀態管理

現在不再停留在“理解”上,而是發出靈魂的拷問,問出真正有工程價值的問題

為什麼 Lit 特別適合用來構建「跨框架組件庫」?
以及,應該怎麼做?


一、為什麼“跨框架組件庫”是一個真實需求

在真實業務中,經常會遇到以下情況:

  • 公司內部同時存在 Vue / React / 原生項目
  • Design System 希望 統一 UI 規範
  • 組件需要被第三方系統接入
  • 微前端架構下,不同子應用技術棧不同

如果用 Vue / React 寫組件庫,通常意味着:

組件和框架強綁定

這正是 Lit 的優勢所在。


二、為什麼 Lit 天然適合這件事

2.1 Lit 的組件是「標準 Web Components」

Lit 組件本質是:

<my-button></my-button>

而不是:

<MyButton />

這意味着:

  • Vue / React / Angular / 原生都能用
  • 沒有運行時依賴衝突
  • 不需要橋接層

2.2 對比三種方案

方案

可行性

代價

Vue 寫 Vue 組件庫

僅 Vue

框架綁定

React 寫 React 組件庫

僅 React

框架綁定

Lit 寫 Web Components

全部

學習成本

Lit 的代價是前期理解,
收益是長期複用能力。


三、組件庫整體架構設計

3.1 推薦的目錄結構

packages/
├── components/
│   ├── button/
│   │   ├── button.ts
│   │   ├── button.styles.ts
│   │   └── index.ts
│   ├── modal/
│   └── index.ts
├── theme/
├── tokens/
└── utils/

特點:

  • 組件高度獨立
  • 不依賴任何框架上下文
  • 只依賴瀏覽器標準

3.2 組件基類設計

export class BaseElement extends LitElement {
  static shadowRootOptions = {
    mode: 'open',
    delegatesFocus: true,
  }
}

所有組件統一繼承,方便:

  • 注入主題
  • 統一行為約束
  • 控制 Shadow DOM 行為

四、一個 Button 組件的完整實現思路

4.1 定義組件

@customElement('ui-button')
export class UIButton extends BaseElement {
  @property({ type: String }) type = 'default'
  @property({ type: Boolean }) disabled = false

  render() {
    return html`
      <button ?disabled=${this.disabled}>
        <slot></slot>
      </button>
    `
  }
}

特點:

  • API 極其穩定
  • 屬性即接口
  • 沒有框架侵入

4.2 樣式隔離策略

static styles = css`
  button {
    padding: 8px 16px;
  }
`
  • Shadow DOM 原生隔離
  • 不污染宿主項目
  • 不怕樣式衝突

五、在 Vue / React 中如何使用

5.1 在 Vue 3 中使用

<ui-button type="primary">
  提交
</ui-button>

注意點:

  • Vue 對 Web Components 是一等公民
  • 只需在 compilerOptions.isCustomElement 中聲明

5.2 在 React 中使用

<ui-button type="primary">
  Submit
</ui-button>

注意:

  • 事件使用 addEventListener
  • 或通過屬性回調
button.addEventListener('click', handler)

六、事件設計:跨框架的關鍵點

6.1 不要暴露框架事件

不推薦:

this.$emit('change')

推薦:

this.dispatchEvent(
  new CustomEvent('change', {
    detail: value,
    bubbles: true,
    composed: true
  })
)

這是 Web Components 標準事件模型


七、主題與樣式系統設計

7.1 使用 CSS Variables

:host {
  --btn-bg: #1677ff;
}

好處:

  • 框架無關
  • 可運行時切換
  • 可被外部覆蓋

7.2 Design Token 層

export const colors = {
  primary: 'var(--color-primary)',
}

形成:

Token → CSS Variables → Component Styles

八、構建與發佈策略

8.1 構建目標

  • 輸出 原生 ES Module
  • 不打包 Lit 本身(peer dependency)
  • 支持 tree-shaking
build: {
  target: 'es2020',
  lib: {
    entry: 'index.ts',
    formats: ['es']
  }
}

8.2 使用方式

import '@your-scope/ui-components'

即可全局註冊組件。


九、Lit 在微前端中的優勢

在微前端場景下,Lit 的優勢會被放大:

  • 不共享運行時
  • 不依賴框架上下文
  • 不怕版本衝突
  • 天然沙箱友好

十、什麼時候不該用 Lit?

必須説清楚邊界:

不適合:

  • 大型業務應用
  • 複雜狀態流轉
  • 強路由依賴

適合:

  • 組件庫
  • Design System
  • 基礎 UI
  • 跨團隊 / 跨系統複用

十一、A Very Important 結論

Lit 並不是“更好的 React / Vue”,
而是“更接近瀏覽器的組件模型”。

當你的目標是:

  • 長期維護
  • 跨技術棧
  • 低運行時成本

Lit 往往是最優解。


最後

如果 you 理解了 Lit,就會發現:

前端並不一定要“越來越重”,
也可以選擇“回到瀏覽器本身”。