Lit.js 入门介绍:与 React 的对比
本指南将介绍 Lit,一个用于构建快速、轻量级 Web Components 的库。我们将通过具体的代码示例,将其核心概念与 React 进行对比,以帮助您更好地理解两者的设计哲学和用法差异。
核心思想:Web Components vs. Virtual DOM
要理解 Lit 和 React 的区别,首先要理解它们所依赖的底层技术。
-
Lit 的核心是 Web Components: 这是一套由浏览器原生支持的技术标准。用 Lit 写的组件最终会成为一个像
<video>或<input>一样的标准 HTML 元素,可以在任何地方使用,不依赖任何框架。Lit 只是一个让创建和使用这些标准组件变得更简单的“语法糖”。 -
React 的核心是 Virtual DOM: 这是一个存在于 JavaScript 内存中的、对真实 DOM 的抽象表示。React 组件的更新会先在 Virtual DOM 中进行计算,然后 React 会找出最高效的方式来更新真实的浏览器 DOM。这是一种框架自有的、非标准化的解决方案。
| 特性 | Lit (Web Components) | React (Virtual DOM) |
|---|---|---|
| 基础技术 | 浏览器原生标准 | 框架自有的抽象 |
| 依赖性 | 无框架依赖,可跨框架使用 | 依赖 React 运行时 |
| 产物 | 标准的自定义 HTML 元素 | React 组件 |
| 样式封装 | Shadow DOM (原生、强隔离) | CSS-in-JS, CSS Modules (社区方案) |
| 生态系统 | 正在快速成长 | 极其庞大和成熟 |
代码对比:创建一个简单的计数器组件
让我们通过一个经典的计数器组件,来直观地感受两者的差异。
Lit 版本
在 Lit 中,我们创建一个继承自 LitElement 的类。
my-counter.js
// 1. 从 'lit' 库导入核心功能
import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';// 2. @customElement 装饰器将这个类注册为一个自定义 HTML 标签 <my-counter>
@customElement('my-counter')
export class MyCounter extends LitElement {// 3. @state 装饰器定义一个私有的、响应式的内部状态@state()private count = 0;// 4. 'static styles' 定义了封装在 Shadow DOM 中的样式,不会影响外部static styles = css`button { font-size: 1.5rem; }span { margin: 0 1rem; }`;// 5. 私有方法来处理点击事件private _increment() {this.count++;}// 6. render() 方法返回组件的 HTML 结构render() {return html`<button @click=${this._increment}>+</button><span>${this.count}</span>`;}
}
index.html
<body><!-- 7. 像使用普通 HTML 标签一样使用我们的组件 --><my-counter></my-counter><script type="module" src="/src/my-counter.js"></script>
</body>
讲解:
- 类和装饰器: Lit 的代码结构更接近标准的 JavaScript 类。装饰器 (
@customElement,@state) 提供了一种简洁的方式来添加元数据。 - 事件处理: 使用
@click语法来绑定事件监听器。 - 模板: 使用
html标签模板来编写 HTML,并用${...}嵌入 JavaScript 表达式。
React 版本
在 React 中,我们通常使用函数式组件和 Hooks。
MyCounter.jsx
// 1. 从 'react' 库导入核心功能
import React, { useState } from 'react';// 2. 定义一个函数式组件
export function MyCounter() {// 3. 使用 useState Hook 来定义一个响应式的状态const [count, setCount] = useState(0);// 4. 定义一个函数来处理点击事件const increment = () => {setCount(count + 1);};// 5. 组件返回 JSX (一种类似 HTML 的语法)return (<div><button onClick={increment}>+</button><span>{count}</span></div>);
}
main.jsx
// 6. 在应用的入口文件中,将组件渲染到 DOM 中
import React from 'react';
import ReactDOM from 'react-dom/client';
import { MyCounter } from './MyCounter.jsx';ReactDOM.createRoot(document.getElementById('root')).render(<MyCounter />);
讲解:
- 函数和 Hooks: React 的现代代码结构以函数为主。Hooks (
useState) 提供了一种在函数组件中“挂载”状态和生命周期的方法。 - 事件处理: 使用
onClick属性来绑定事件监听器。 - 模板 (JSX): 使用 JSX 语法来编写 HTML 结构,并用
{...}嵌入 JavaScript 表达式。
总结
- Lit 更接近底层标准: 它的语法和概念(类、Shadow DOM、自定义元素)都建立在浏览器原生功能之上,学习曲线相对平缓,产物也更通用。
- React 更像一个完备的框架: 它有自己的一套编程范式(函数式组件、Hooks、JSX)和庞大的生态系统,为大型复杂应用提供了强大的抽象能力和丰富的工具支持。
如何选择?
- 如果你想构建可以跨框架复用的 UI 组件库,或者追求极致的轻量和性能,Lit 是一个绝佳的选择。
- 如果你正在构建一个大型、复杂的单页应用,并且希望利用最庞大、最成熟的社区生态,React 依然是目前最稳妥的选择。
