
本章核心问题: 如何快速开始Lit开发?最小化的Lit组件需要哪些部分?装饰器和原生API有什么区别?
本章你将掌握:三种不同的开发环境选择(Playground、CDN、Starter Kit) LitElement 基类和 html 标签函数的作用 使用装饰器或原生API注册自定义元素 从零创建并运行你的第一个 Lit 组件
开启Lit开发之旅有多种途径,可以根据不同的需求选择最合适的方式,从无需任何安装的在线环境到功能完备的专业开发工作流。
<script type="module">标签中引入Lit的核心库包,就可以开始编写组件了 。这种方式清晰地展示了Lit只是一个标准的JavaScript模块,有助于揭开其“神秘面纱”。
本教程将引导你使用官方的JavaScript入门套件,逐步了解一个标准的Lit项目结构及其中的工具链。
LitElement与html一个最基础的 Lit 组件由几个核心部分构成。让我们通过一个经典的“Hello, World”示例来逐一解析:
import { LitElement, html } from 'lit';
class MyElement extends LitElement {
render() {
return html`<h1>Hello, World!</h1>`;
}
}import { LitElement, html } from 'lit';:这行代码从lit包中导入了两个核心模块。LitElement是所有Lit组件的基类,提供了响应式更新等核心功能 。 html是一个标签函数,用于创建Lit的声明式模板 。
class MyElement extends LitElement:我们通过创建一个继承自LitElement的JavaScript类来定义一个新组件。这种面向对象的方式使得组件的逻辑、状态和模板得以封装。
render():这是LitElement中的一个生命周期方法,负责定义组件的UI结构 。当组件需要更新时,这个方法会被调用,并且它必须返回一个由
html标签函数创建的TemplateResult对象。
定义了组件类之后,还需要告知浏览器这个新元素的存在,这个过程称为“注册”。
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('my-element')
export class MyElement extends LitElement {
render() {
return html`<h1>Hello, World!</h1>`;
}
}@customElement('my-element'):这是一个装饰器(Decorator),它是注册自定义元素的一种便捷语法。它所做的事情等同于调用浏览器原生的customElements.define() API 。括号中的字符串
'my-element'是你为组件定义的HTML标签名。自定义元素标签名必须包含一个连字符(-),这是W3C标准的要求,用以区分自定义元素和原生HTML元素。
如果你不使用装饰器(例如在纯JavaScript项目中),可以直接调用标准API来完成注册:
class MyElement extends LitElement {
//...
}
customElements.define('my-element', MyElement);两种方式效果完全相同,装饰器只是提供了一种更简洁、更具声明性的语法。这再次体现了Lit紧密贴合Web平台标准的理念。
一旦组件被成功注册,它就成为了一个功能完备的HTML元素。你可以像使用任何内置标签一样在你的HTML文件中使用它 。
在你的index.html文件中,只需添加以下代码:
<my-element></my-element>当浏览器加载页面时,它会识别这个标签,找到与之关联的MyElement类,实例化该组件,并将其渲染到页面上。至此,你已经完成了从零到一的整个流程,并在屏幕上看到了你的第一个Lit组件——这是体验Lit强大功能的第一个"啊哈!"时刻。
让我们创建一个更完整的示例,展示 Lit 组件的基本功能,包括属性、状态和事件处理:
方式1:使用 TypeScript 和装饰器(推荐)
// greeting-card.ts
import { LitElement, html, css } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
@customElement('greeting-card')
export class GreetingCard extends LitElement {
// 定义组件样式(封装在 Shadow DOM 中)
static styles = css`
:host {
display: block;
padding: 20px;
border-radius: 8px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-family: Arial, sans-serif;
max-width: 400px;
margin: 20px auto;
}
h1 {
margin: 0 0 16px 0;
font-size: 24px;
}
input {
padding: 8px 12px;
border: none;
border-radius: 4px;
font-size: 16px;
width: 200px;
margin-right: 8px;
}
button {
padding: 8px 16px;
border: none;
border-radius: 4px;
background: white;
color: #667eea;
font-size: 16px;
cursor: pointer;
transition: transform 0.2s;
}
button:hover {
transform: scale(1.05);
}
.greeting {
margin-top: 20px;
padding: 16px;
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
font-size: 18px;
}
`;
// 公共属性:可从外部传入
@property({ type: String }) title = 'Lit 问候组件';
// 内部状态
@state() private userName = '';
@state() private greeting = '';
// 处理输入变化
private handleInput(e: Event) {
const input = e.target as HTMLInputElement;
this.userName = input.value;
}
// 生成问候语
private generateGreeting() {
if (this.userName.trim()) {
const hour = new Date().getHours();
let timeGreeting = '你好';
if (hour < 6) timeGreeting = '凌晨好';
else if (hour < 12) timeGreeting = '早上好';
else if (hour < 14) timeGreeting = '中午好';
else if (hour < 18) timeGreeting = '下午好';
else if (hour < 22) timeGreeting = '晚上好';
else timeGreeting = '深夜好';
this.greeting = `${timeGreeting},${this.userName}!欢迎体验 Lit 的魔力 ✨`;
} else {
this.greeting = '请输入您的名字';
}
}
render() {
return html`
<h1>${this.title}</h1>
<div>
<input
type="text"
placeholder="请输入您的名字"
.value=${this.userName}
@input=${this.handleInput}
/>
<button @click=${this.generateGreeting}>
生成问候语
</button>
</div>
${this.greeting ? html`
<div class="greeting">
${this.greeting}
</div>
` : ''}
`;
}
}方式2:使用纯 JavaScript(无装饰器)
// greeting-card-js.js
import { LitElement, html, css } from 'lit';
export class GreetingCard extends LitElement {
static properties = {
title: { type: String },
userName: { type: String, state: true },
greeting: { type: String, state: true }
};
static styles = css`
/* 样式同上 */
`;
constructor() {
super();
this.title = 'Lit 问候组件';
this.userName = '';
this.greeting = '';
}
handleInput(e) {
this.userName = e.target.value;
}
generateGreeting() {
// 逻辑同上
}
render() {
// 模板同上
}
}
// 注册组件
customElements.define('greeting-card', GreetingCard);方式3:使用 CDN 快速体验(无需构建工具)
创建一个 index.html 文件:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一个 Lit 组件</title>
<script type="module">
import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js';
class GreetingCard extends LitElement {
static properties = {
title: { type: String },
userName: { type: String },
greeting: { type: String }
};
static styles = css`
:host {
display: block;
padding: 20px;
background: #f0f0f0;
border-radius: 8px;
max-width: 400px;
}
button {
background: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
`;
constructor() {
super();
this.title = '欢迎使用 Lit!';
this.userName = '';
this.greeting = '';
}
render() {
return html`
<h1>${this.title}</h1>
<div>
<input
type="text"
placeholder="输入名字"
@input=${(e) => this.userName = e.target.value}
/>
<button @click=${() => {
this.greeting = this.userName
? `你好,${this.userName}!`
: '请先输入名字';
}}>
打招呼
</button>
</div>
${this.greeting ? html`<p>${this.greeting}</p>` : ''}
`;
}
}
customElements.define('greeting-card', GreetingCard);
</script>
</head>
<body>
<h1>Lit 入门示例</h1>
<!-- 使用组件,传入自定义标题 -->
<greeting-card title="我的问候卡片"></greeting-card>
<!-- 可以创建多个实例 -->
<greeting-card title="另一个问候卡片"></greeting-card>
</body>
</html>运行和测试
index.html关键学习点:
@property 和 @state 的区别和用法@event 语法绑定事件.value 用于属性绑定,value 用于特性绑定通过本章学习,你已经掌握了:
LitElement:所有 Lit 组件的基类,提供响应式更新能力html:标签函数,用于创建声明式模板render():生命周期方法,返回组件的 UI 结构@customElement('my-element') - 更简洁声明式customElements.define() - 直接调用标准 API<my-element></my-element>⚡ 关键认知:Lit 不是在创造新的概念,而是在增强 Web 标准。你写的每个组件都是标准的 Web Component。
在下一章中,我们将深入探索 lit-html 的强大功能,学习如何创建动态、响应式的模板。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。