好的,我们将结合 HTMX、UcoCSS 原子化样式表技术,以及 TypeScript 高阶函数,来展示一个实际应用。我们将创建一个简单的待办事项 (Todo)应用来展示如何在 HTMX 环境中使用 TypeScript 的高阶函数,以及如何用 UcoCSS 的原子化样式表来简化样式管理。

项目结构

my-htmx-todo/
├── src/
│   ├── index.ts
│   └── todo.ts
├── public/
│   ├── index.html
│   └── styles.css
├── tsconfig.json
├── package.json
└── bunfig.toml

1. 初始化项目

创建项目目录并初始化 Bun 项目

mkdir my-htmx-todo
cd my-htmx-todo
bun init

安装 Elysia 和其他依赖

bun add elysia htmx
bun add -d typescript

创建 tsconfig.json

bun add --dev typescript
bun x tsc --init

编辑生成的 tsconfig.json 文件:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"]
}

2. 创建 ToDo 模块

src 目录下创建 todo.ts 文件,用于处理 ToDo 项相关的逻辑。

interface TodoItem {
  id: number;
  task: string;
  completed: boolean;
}
 
let todos: TodoItem[] = [];
let currentId = 1;
 
// 高阶函数进行错误处理
function withErrorHandler<T extends (...args: any[]) => Promise<any>>(asyncFunc: T) {
  return async (...args: Parameters<T>): Promise<ReturnType<T> | { error: any }> => {
    try {
      const result = await asyncFunc(...args);
      return result;
    } catch (error) {
      console.error("An error occurred:", error);
      return { error };
    }
  };
}
 
export const addTodo = withErrorHandler(async (task: string): Promise<TodoItem> => {
  const newTodo = { id: currentId++, task, completed: false };
  todos.push(newTodo);
  return newTodo;
});
 
export const getTodos = withErrorHandler(async (): Promise<TodoItem[]> => {
  return todos;
});

3. 创建 Elysia 服务器

src 目录下创建 index.ts 文件,作为应用的入口。

import { Elysia } from 'elysia';
import { addTodo, getTodos } from './todo';
 
const app = new Elysia();
 
app.get('/', async (req, res) => {
  res.type('text/html');
  res.sendFile('public/index.html');
});
 
app.get('/todos', async (req, res) => {
  const todos = await getTodos();
  res.json(todos);
});
 
app.post('/todos', async (req, res) => {
  const { task } = await req.json();
  const newTodo = await addTodo(task);
  res.json(newTodo);
});
 
app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

4. 创建前端页面与 HTMX 交互

public 目录中创建 index.html 文件。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>HTMX Todo List</title>
  <script src="https://unpkg.com/htmx.org@1.5.0"></script>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1 class="text-2xl font-bold">Todo List</h1>
 
  <div>
    <form id="todo-form" hx-post="/todos" hx-trigger="submit" hx-target="#todos">
      <input type="text" name="task" placeholder="New Todo" class="border p-2" required>
      <button type="submit" class="bg-blue-500 text-white p-2">Add</button>
    </form>
  </div>
 
  <div id="todos" hx-get="/todos" hx-trigger="load">
    <!-- HTMX will load todos here -->
  </div>
</body>
</html>

styles.css 文件配置 UcoCSS 原子化样式:

/* Source: UcoCSS or similar atomic CSS library */
.text-2xl {
  font-size: 1.5rem;
}
 
.font-bold {
  font-weight: 700;
}
 
.border {
  border-width: 1px;
}
 
.p-2 {
  padding: 0.5rem;
}
 
.bg-blue-500 {
  background-color: #3b82f6;
}
 
.text-white {
  color: #ffffff;
}

5. 启动服务器

使用 Bun 启动服务器:

bun run src/index.ts

总结

通过这个完整的项目结构和代码示例,我们展示了如何结合 HTMX、UcoCSS 和 TypeScript 高阶函数来创建一个简单的 Todo 应用。以下是主要的实现步骤和关键点:

  1. 初始化项目:我们创建了项目目录并初始化了 Bun 项目,同时安装了 Elysia 和 HTMX 作为主要的框架和库。
  2. 创建 ToDo 模块:定义了 ToDo 项目管理的逻辑,其中包括通过高阶函数进行错误处理的 addTodogetTodos 函数。
  3. 创建 Elysia 服务器:在 Elysia 服务器中设置了不同的路由,包括获取和添加 ToDo 项。
  4. 创建前端页面:使用 HTMX 实现前端与后端的交互,并使用 UcoCSS 原子化样式进行样式管理。

这种结构和方法不仅提高了代码的复用性和可读性,还使得整个应用更加模块化和易于维护。希望这个示例对你有所帮助,如果有任何问题或需要进一步的帮助,请随时提问!