关于 json-to-html-table-with-lit
面向 Lit Web 开发者的教程,介绍将 JSON URL 或内嵌 JSON 渲染为 HTML 表格,并添加单元格编辑、事件通知及自定义表头。
主要功能
- 01从 URL 或内嵌 JSON 生成表格
- 02编辑表格单元格
- 03通过事件获取单元格数据
- 04按 JSON 键替换表头单元格
- 05使用 CSS 自定义属性设置样式
适用场景
- 01在网页中展示 JSON 数据
- 02为 JSON 表格添加单元格编辑功能
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rodydavis/ skills --skill json-to-html-table-with-lit安装后在 Claude Code 中输入/json-to-html-table-with-lit确认已加载。
详细介绍
使用 Lit 将 JSON 转换为 HTML 表格
本文将介绍如何设置 Lit Web 组件,并使用它根据 JSON URL 或内嵌 JSON 创建 HTML 表格。
前提条件
- Vscode
- Node >= 16
- Typescript
入门
首先,在终端中导航到项目所在位置,然后运行以下命令:
npm init @vitejs/app --template lit-ts
接着输入项目名称 lit-html-table,然后在 vscode 中打开项目并安装依赖项:
cd lit-html-table
npm i lit
npm i -D @types/node
code .
按以下内容更新 vite.config.ts:
import { defineConfig } from "vite";
import { resolve } from "path";
export default defineConfig({
base: "/lit-html-table/",
build: {
lib: {
entry: "src/lit-html-table.ts",
formats: ["es"],
},
rollupOptions: {
input: {
main: resolve(__dirname, "index.html"),
},
},
},
});
模板
打开 index.html 并按以下内容更新:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>JSON to Lit HTML Table</title>
<script type="module" src="/src/lit-html-table.ts"></script>
</head>
<body>
<lit-html-table src="https://jsonplaceholder.typicode.com/posts">
</lit-html-table>
</body>
</html>
在本示例中,我们向 Web 组件传递了一个 src 属性,但也可以添加一个 script 标签,将 type 属性设为 application/json,并在其中填写 JSON 内容。
如果需要替换表格标题单元格,可以提供一个元素,并将其 slot 名称设为 JSON 对象中的键。
Web 组件
更新组件之前,我们需要将 my-element.ts 重命名为 lit-html-table.ts。
打开 lit-html-table.ts 并按以下内容更新:
import { html, css, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
type ObjectData = { [key: string]: any };
@customElement("lit-html-table")
export class LitHtmlTable extends LitElement {
@property() src = "";
data?: ObjectData[];
static styles = css`
tr {
text-align: var(--table-tr-text-align, left);
vertical-align: var(--table-tr-vertical-align, top);
padding: var(--table-tr-padding, 10px);
}
`;
render() {
// Check if data is loaded
if (!this.values) {
return html`<slot name="loading">Loading...</slot>`;
}
// Check if items are not empty
if (this.values.length === 0) {
return html`<slot name="empty">No Items Found!</slot>`;
}
// Convert JSON to HTML Table
return html`
<table>
<thead>
<tr>
${Object.keys(this.values[0]).map((key) => {
const name = key.replace(/\b([a-z])/g, (_, val) =>
val.toUpperCase()
);
return html`<th>
<slot name="${key}">${name}</slot>
</th>`;
})}
</tr>
</thead>
<tbody>
${this.values.map((item) => {
return html`
<tr>
${Object.values(item).map((row) => {
return html`<td>${row}</td>`;
})}
</tr>
`;
})}
</tbody>
</table>
`;
}
async firstUpdated() {
await this.fetchData();
}
// Download the latest json and update it locally
async fetchData() {
let _data: any;
if (this.src.length > 0) {
// If a src attribute is set prefer it over any slots
_data = await fetch(this.src).then((res) => res.json());
} else {
// If no src attribute is set then grab the inline json in the slot
const elem = this.parentElement?.querySelector(
'script[type="application/json"]'
) as HTMLScriptElement;
if (elem) _data = JSON.parse(elem.innerHTML);
}
this.values = this.transform(_data ?? []);
this.requestUpdate();
}
transform(data: any) {
return data;
}
}
我们定义了一些 CSS 自定义属性 来设置表格单元格的样式,也可以在此添加更多属性。
如果一切顺利,运行命令 npm run dev,应该会看到以下内容:
![]()
编辑
如果我们想支持编辑任意单元格,该怎么做?借助 Lit 和 Web Components,我们可以逐步增强体验,而无需更改 HTML。
在类的顶部添加以下布尔属性:
@property({ type: Boolean }) editable = false;
现在更新 render 方法中的 tbody 标签:
<tbody>
${this.values.map((item, index) => {
return html`
<tr>
${Object.entries(item).map((row) => {
return html`<td>
${this.editable
? html`<input
value="${row[1]}"
type="text"
@input=${(e: any) => {
const value = e.target.value;
const key = row[0];
const current = this.values![index];
current[key] = value;
this.values![index] = current;
this.requestUpdate();
this.dispatchEvent(
new CustomEvent("input-cell", {
detail: {
index: index,
data: current,
},
})
);
}}
/>`
: html`${row[1]}`}
</td>`;
})}
</tr>
`;
})}
</tbody>
检查 editable 是否为 true,如果是,则返回一个带有事件监听器的输入框,以更新数据并派发 input 事件。
将 editable 属性添加到 index.html:
<lit-html-table editable> ... </lit-html-table>
重新加载后,表格应如下所示,并且可以编辑任意单元格。
![]()
可以在 index.html 的闭合 body 标签之前添加事件监听器,以获取最新值或单元格信息:
<script>
const elem = document.querySelector("lit-html-table");
elem.addEventListener(
"input-cell",
(e) => {
// Index and data for the individual cell
const { index, data } = e.detail;
// New array of json items
const values = elem.values;
},
false
);
</script>
还可以进一步扩展此功能:检查值的类型,并返回颜色、数字或复选框输入框。
结论
如果你想进一步了解如何使用 Lit 构建,可以阅读这里的文档。Lit playground 上也有一个示例这里。 此示例的源代码可在此处找到。