用 Lit 构建跨 Vue / React 的组件库完整实践
在前面的几篇中,已经把 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,就会发现:
前端并不一定要“越来越重”,
也可以选择“回到浏览器本身”。

浙公网安备 33010602011771号