第三章:核心属性详解
3.1 HTTP 请求属性
HTMX 提供了完整的 HTTP 方法支持:
hx-get - 获取数据
<!-- 基础用法 -->
<button hx-get="/api/users">加载用户列表</button>
<!-- 带查询参数 -->
<input type="search"
hx-get="/api/search"
hx-target="#results"
name="q"
placeholder="搜索...">
<!-- 动态 URL -->
<button hx-get="/api/user/{{ user.id }}/details">查看详情</button>
hx-post / hx-put / hx-patch / hx-delete
<!-- 创建资源 -->
<form hx-post="/api/users" hx-target="#user-list">
<input name="name" placeholder="姓名">
<input name="email" placeholder="邮箱">
<button type="submit">创建用户</button>
</form>
<!-- 更新资源 -->
<button hx-put="/api/users/123" hx-target="this">更新</button>
<!-- 部分更新 -->
<button hx-patch="/api/users/123" hx-target="this">部分更新</button>
<!-- 删除资源 -->
<button hx-delete="/api/users/123"
hx-confirm="确定删除吗?"
hx-target="closest tr">删除</button>
3.2 目标与交换属性
hx-target - 指定更新目标
<!-- 基础选择器 -->
<button hx-get="/content" hx-target="#result"></button>
<!-- 特殊关键字 -->
<button hx-get="/content" hx-target="this">替换自己</button>
<!-- 最近的父元素 -->
<div class="card">
<button hx-get="/detail" hx-target="closest .card">展开</button>
</div>
<!-- 查找子元素 -->
<div class="container">
<button hx-get="/content" hx-target="find .display">加载</button>
<div class="display"></div>
</div>
hx-swap - 控制交换方式
<!-- 带修饰符的交换 -->
<button hx-get="/content"
hx-target="#result"
hx-swap="innerHTML transition:true">
带过渡动画
</button>
<!-- 延迟交换(等待 CSS 动画完成) -->
<button hx-get="/content"
hx-swap="innerHTML settle:500ms">
延迟 500ms 交换
</button>
<!-- 滚动控制 -->
<button hx-get="/page/2"
hx-target="#content"
hx-swap="beforeend scroll:bottom">
加载更多并滚动到底部
</button>
<!-- 显示窗口顶部 -->
<button hx-get="/content"
hx-swap="innerHTML show:window:top">
交换后滚动到页面顶部
</button>
hx-swap 修饰符:
| 修饰符 | 说明 | 示例 |
|---|
transition | 启用视图过渡 | transition:true |
swap | 交换延迟时间 | swap:300ms |
settle | 稳定延迟时间 | settle:100ms |
scroll | 滚动方向 | scroll:top/bottom |
show | 显示元素 | show:window:top |
focus-scroll | 聚焦时滚动 | focus-scroll:true |
3.3 触发器属性
hx-trigger - 定义触发事件
<!-- 点击触发(默认) -->
<button hx-get="/content" hx-trigger="click">点击</button>
<!-- 鼠标悬停 -->
<div hx-get="/preview" hx-trigger="mouseenter">悬停预览</div>
<!-- 输入时实时搜索(带防抖) -->
<input type="search"
hx-get="/api/search"
hx-target="#results"
hx-trigger="keyup changed delay:500ms"
name="q"
placeholder="输入搜索...">
<!-- 失去焦点时触发 -->
<input hx-post="/api/validate"
hx-trigger="blur"
hx-target="next .error">
<span class="error"></span>
<!-- 自定义事件 -->
<button hx-get="/content" hx-trigger="customEvent"></button>
<script>document.dispatchEvent(new Event('customEvent'))</script>
<!-- 轮询 -->
<div hx-get="/status" hx-trigger="every 5s">状态会每 5 秒更新</div>
<!-- 进入视口时加载(懒加载) -->
<div hx-get="/lazy-content" hx-trigger="revealed">滚动到这里时加载</div>
<!-- 加载时触发 -->
<div hx-get="/init" hx-trigger="load">页面加载时自动获取</div>
触发器修饰符:
| 修饰符 | 说明 | 示例 |
|---|
once | 只触发一次 | click once |
changed | 值变化时触发 | keyup changed |
delay | 延迟触发 | keyup delay:500ms |
throttle | 节流 | scroll throttle:100ms |
from | 指定来源 | click from:#button |
target | 目标元素 | click target:#modal |
consume | 阻止冒泡 | click consume |
queue | 队列策略 | keyup queue:last |
3.4 指示器与状态
hx-indicator - 加载指示器
<!-- 基础用法 -->
<button hx-get="/slow-endpoint" hx-indicator="#spinner">
加载数据
</button>
<div id="spinner" class="htmx-indicator">⏳ 加载中...</div>
<!-- 使用 CSS 类 -->
<style>
.htmx-indicator {
display: none;
}
.htmx-request .htmx-indicator {
display: inline;
}
.htmx-request.htmx-indicator {
display: inline;
}
</style>
<!-- 最简形式(自动查找子元素) -->
<button hx-get="/content">
点击
<span class="htmx-indicator">⏳</span>
</button>
hx-disabled-elt - 禁用元素
<!-- 请求时禁用按钮 -->
<form hx-post="/submit" hx-disabled-elt="this">
<input name="data">
<button type="submit">提交</button>
<!-- 提交期间按钮自动禁用 -->
</form>
<!-- 禁用多个元素 -->
<form hx-post="/submit" hx-disabled-elt="find button, find input"
hx-indicator=".loading">
<input name="data">
<button type="submit">提交</button>
<span class="loading htmx-indicator">处理中...</span>
</form>
3.5 同步与请求控制
hx-sync - 同步请求
<!-- 在表单范围内排队请求 -->
<form hx-sync="this:queue all">
<button hx-post="/action1">动作 1</button>
<button hx-post="/action2">动作 2</button>
</form>
<!-- 策略选项 -->
<!-- queue first: 只保留第一个,忽略后续 -->
<!-- queue last: 取消前面的,保留最后一个 -->
<!-- queue all: 全部排队依次执行 -->
<!-- drop: 如果正在请求,则丢弃新请求 -->
<!-- abort: 取消当前请求,执行新请求 -->
<!-- replace: 替换当前请求(默认) -->
hx-confirm - 确认对话框
<!-- 简单确认 -->
<button hx-delete="/api/users/123" hx-confirm="确定删除此用户吗?">
删除
</button>
<!-- 使用浏览器默认 confirm -->
<form hx-post="/dangerous-action" hx-confirm="此操作不可撤销,继续吗?">
<button>执行危险操作</button>
</form>
3.6 参数与值处理
hx-vals - 添加额外值
<!-- 添加静态值 -->
<button hx-post="/vote"
hx-vals='{"type": "upvote", "id": 123}'>
👍 点赞
</button>
<!-- 动态计算值(使用 JS) -->
<button hx-post="/action"
hx-vals="js:{timestamp: Date.now(), random: Math.random()}">
提交(带动态值)
</button>
<!-- 从元素获取值 -->
<form hx-post="/submit"
hx-vals='{"csrf": document.querySelector("[name=csrf]").value}'
>
...
</form>
hx-include - 包含额外元素
<!-- 包含其他输入框的值 -->
<input type="text" id="search-term" placeholder="搜索词">
<button hx-get="/api/search"
hx-include="#search-term, [name='category']"
hx-target="#results">
搜索
</button>
<!-- 包含最近的表单 -->
<button hx-post="/save" hx-include="closest form">保存</button>
hx-params - 控制参数发送
<!-- 只发送指定参数 -->
<form hx-post="/submit" hx-params="name, email"
>
<input name="name">
<input name="email">
<input name="hidden_field" type="hidden"> <!-- 不会被发送 -->
</form>
<!-- 排除指定参数 -->
<form hx-post="/submit" hx-params="not password_confirm"
>
<input name="password" type="password">
<input name="password_confirm" type="password"> <!-- 不会被发送 -->
</form>
<!-- 不发送任何参数 -->
<button hx-get="/clear" hx-params="none">清空</button>
<!-- 发送所有参数(包括空值) -->
<form hx-post="/submit" hx-params="*">...</form>
3.7 选择器与片段
hx-select - 选择部分内容
<!-- 只使用响应中的特定部分 -->
<button hx-get="/full-page"
hx-target="#sidebar"
hx-select="#sidebar-content"
hx-swap="outerHTML">
更新侧边栏
</button>
<!-- 后端返回完整页面,但只提取 #sidebar-content -->
hx-select-oob - 带外更新
<!-- 同时更新多个区域 -->
<button hx-post="/add-to-cart"
hx-target="#cart-items"
hx-select-oob="#cart-count:afterend, #cart-total:afterend"
>
加入购物车
</button>
<!-- 后端返回:
<div id="cart-items">...新购物车内容...</div>
<span id="cart-count">3</span>
<span id="cart-total">¥299</span>
-->
3.8 属性速查表
| 属性 | 用途 | 示例 |
|---|
hx-get/post/put/patch/delete | 发起 HTTP 请求 | hx-get="/api/data" |
hx-target | 指定更新目标 | hx-target="#result" |
hx-swap | 控制交换方式 | hx-swap="innerHTML" |
hx-trigger | 定义触发事件 | hx-trigger="click" |
hx-indicator | 显示加载状态 | hx-indicator="#spinner" |
hx-confirm | 确认对话框 | hx-confirm="确定吗?" |
hx-vals | 添加额外参数 | hx-vals='{"key":"val"}' |
hx-include | 包含其他元素 | hx-include="#input" |
hx-params | 控制参数 | hx-params="name,email" |
hx-select | 选择内容 | hx-select="#content" |
hx-select-oob | 带外更新 | hx-select-oob="#count" |
hx-sync | 请求同步 | hx-sync="this:queue" |
hx-disabled-elt | 禁用元素 | hx-disabled-elt="this" |
hx-push-url | 推送 URL | hx-push-url="true" |
hx-boost | 增强链接/表单 | hx-boost="true" |
下一章预告:第四章将深入讲解触发器系统和事件处理。
第三章完