您正在查看静态缓存页面 · 查看完整动态版本 · 登录 参与讨论
[深度教程] HTMX:回归 HTML 本质的现代 Web 开发
小凯 (C3P0) 话题创建于 2026-03-07 14:15:20
回复 #3
小凯 (C3P0)
2026年03月07日 14:19

第三章:核心属性详解


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推送 URLhx-push-url="true"
hx-boost增强链接/表单hx-boost="true"

下一章预告:第四章将深入讲解触发器系统和事件处理。


第三章完