好的, 让我们通过一个复杂的示例来展示在 Bun 环境下, 使用 Elysia 作为后端和 HTMX 作为前端时如何传递参数。这个示例将包含一个用户管理系统, 涉及用户列表、添加用户和编辑用户的功能。

首先, 我们来设置 Elysia 后端:

import { Elysia, t } from 'elysia'
import { html } from '@elysiajs/html'
 
const app = new Elysia()
  .use(html())
 
// 用户类型定义
type User = {
  id: number
  name: string
  email: string
  role: 'admin' | 'user'
}
 
// 模拟数据库
let users: User[] = [
  { id: 1, name: 'John Doe', email: 'john@example.com', role: 'admin' },
  { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'user' },
]
 
// 主页路由
app.get('/', () => `
  <html>
    <head>
      <script src="https://unpkg.com/htmx.org@1.9.6"></script>
    </head>
    <body>
      <h1>User Management System</h1>
      <div id="user-list" hx-get="/users" hx-trigger="load">Loading users...</div>
      <button hx-get="/users/new" hx-target="#user-form">Add New User</button>
      <div id="user-form"></div>
    </body>
  </html>
`)
 
// 获取用户列表
app.get('/users', () => {
  return `
    <table>
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Email</th>
        <th>Role</th>
        <th>Actions</th>
      </tr>
      ${users.map(user => `
        <tr>
          <td>${user.id}</td>
          <td>${user.name}</td>
          <td>${user.email}</td>
          <td>${user.role}</td>
          <td>
            <button hx-get="/users/${user.id}/edit" hx-target="#user-form">Edit</button>
            <button hx-delete="/users/${user.id}" hx-target="closest tr" hx-confirm="Are you sure?">Delete</button>
          </td>
        </tr>
      `).join('')}
    </table>
  `
})
 
// 新用户表单
app.get('/users/new', () => `
  <form hx-post="/users" hx-target="#user-list" hx-swap="outerHTML">
    <input type="text" name="name" placeholder="Name" required>
    <input type="email" name="email" placeholder="Email" required>
    <select name="role" required>
      <option value="user">User</option>
      <option value="admin">Admin</option>
    </select>
    <button type="submit">Add User</button>
  </form>
`)
 
// 添加新用户
app.post('/users', ({ body }) => {
  const newUser: User = {
    id: users.length + 1,
    name: body.name,
    email: body.email,
    role: body.role as 'admin' | 'user'
  }
  users.push(newUser)
  return app.handlers.get['/users']()
}, {
  body: t.Object({
    name: t.String(),
    email: t.String(),
    role: t.Union([t.Literal('admin'), t.Literal('user')])
  })
})
 
// 编辑用户表单
app.get('/users/:id/edit', ({ params }) => {
  const user = users.find(u => u.id === parseInt(params.id))
  if (!user) return 'User not found'
  
  return `
    <form hx-put="/users/${user.id}" hx-target="#user-list" hx-swap="outerHTML">
      <input type="text" name="name" value="${user.name}" required>
      <input type="email" name="email" value="${user.email}" required>
      <select name="role" required>
        <option value="user" ${user.role === 'user' ? 'selected' : ''}>User</option>
        <option value="admin" ${user.role === 'admin' ? 'selected' : ''}>Admin</option>
      </select>
      <button type="submit">Update User</button>
    </form>
  `
})
 
// 更新用户
app.put('/users/:id', ({ params, body }) => {
  const index = users.findIndex(u => u.id === parseInt(params.id))
  if (index === -1) return 'User not found'
  
  users[index] = { ...users[index], ...body }
  return app.handlers.get['/users']()
}, {
  body: t.Object({
    name: t.String(),
    email: t.String(),
    role: t.Union([t.Literal('admin'), t.Literal('user')])
  })
})
 
// 删除用户
app.delete('/users/:id', ({ params }) => {
  users = users.filter(u => u.id !== parseInt(params.id))
  return ''
})
 
app.listen(3000)

这个例子展示了 Elysia 和 HTMX 之间的几种参数传递方式:

  1. URL 参数: 在编辑和删除用户时, 我们通过 URL 传递用户 ID。例如: /users/:id/edit/users/:id

  2. 表单数据: 在添加和更新用户时, 我们使用表单提交数据。HTMX 会自动将表单数据序列化并发送到服务器。

  3. HTMX 属性: 我们使用多种 HTMX 属性来控制行为, 如 hx-get, hx-post, hx-put, hx-delete, hx-target, hx-swap 等。

  4. 查询参数: 虽然这个例子中没有使用, 但你也可以通过 URL 查询参数传递数据, 例如: /users?page=1&limit=10

  5. 自定义请求头: HTMX 允许你设置自定义请求头, 可以用来传递额外的元数据。

  6. JSON 数据: 对于更复杂的数据结构, 你可以使用 JSON 格式通过请求体发送数据。

在这个例子中:

  • 主页 (/)加载时, HTMX 自动发起请求获取用户列表。
  • 点击”Add New User”按钮会加载新用户表单。
  • 提交新用户表单时, 数据通过 POST 请求发送到服务器。
  • 编辑用户时, 先加载带有用户当前数据的表单, 然后通过 PUT 请求更新数据。
  • 删除用户通过 DELETE 请求实现。

这个示例展示了如何使用 Elysia 和 HTMX 创建一个动态的、无需页面刷新的用户管理系统。它利用了 HTMX 的声明式属性来处理 AJAX 请求, 而 Elysia 则负责处理这些请求并返回适当的 HTML 片段。