hx-get 与 hx-post 基础请求
hx-get 与 hx-post 基础请求
htmx 的核心能力在于让 HTML 元素直接发起 HTTP 请求。本文将深入讲解 hx-get、hx-post 以及相关的请求控制属性,帮助你掌握 htmx 最基础也是最常用的交互模式。
hx-get:获取数据
hx-get 是最常用的 htmx 属性,它让元素在被触发时向指定 URL 发起 GET 请求。
基础用法
<div hx-get="/api/user-info">
点击加载用户信息
</div>默认情况下,hx-get 在元素的 click 事件上触发。点击 div 后,htmx 会向 /api/user-info 发起 GET 请求,并将返回的 HTML 替换该 div 的内容。
链接的渐进增强
<a href="/profile" hx-get="/profile" hx-target="#content">
查看个人资料
</a>这个链接同时具有传统 href 和 hx-get。如果 htmx 未加载,点击会正常跳转;如果 htmx 已加载,则只更新 #content 区域。
带查询参数
<input type="search"
name="q"
hx-get="/api/search"
hx-trigger="keyup changed delay:500ms"
hx-target="#search-results" />输入框的值会自动作为查询参数附加到 URL:/api/search?q=用户输入。
提示:htmx 会自动收集带有
name属性的表单元素的值,作为请求参数发送。
hx-post:提交数据
hx-post 用于向服务器提交数据,通常配合表单使用。
基础表单提交
<form hx-post="/api/login" hx-target="#message">
<input type="email" name="email" placeholder="邮箱" required />
<input type="password" name="password" placeholder="密码" required />
<button type="submit">登录</button>
</form>
<div id="message"></div>表单提交时,htmx 会自动序列化所有表单字段的值,以 application/x-www-form-urlencoded 格式发送 POST 请求。服务器返回的 HTML 将替换 #message 的内容。
非表单元素的 POST
<button hx-post="/api/like/42"
hx-target="this"
hx-swap="outerHTML">
❤️ 点赞
</button>任何元素都可以使用 hx-post。上例中,点击按钮向 /api/like/42 发送 POST 请求,然后用返回的 HTML 替换按钮本身(可能变为”已点赞”状态)。
文件上传
<form hx-post="/api/upload"
hx-encoding="multipart/form-data"
hx-target="#upload-status">
<input type="file" name="document" />
<button type="submit">上传</button>
</form>
<div id="upload-status"></div>上传文件时需要显式设置 hx-encoding="multipart/form-data",htmx 会自动处理 FormData 的构建和发送。
注意:htmx 2.x 支持文件上传的进度事件,可以通过
htmx:xhr:progress事件监听上传进度。
其他 HTTP 方法
htmx 支持完整的 RESTful HTTP 方法集合:
<!-- PUT:完整更新资源 -->
<button hx-put="/api/users/123" hx-include="#edit-form">
保存修改
</button>
<!-- DELETE:删除资源 -->
<button hx-delete="/api/posts/456"
hx-confirm="确定要删除这篇文章吗?"
hx-target="closest article"
hx-swap="delete">
删除
</button>
<!-- PATCH:部分更新 -->
<form hx-patch="/api/settings">
<input type="checkbox" name="notifications" checked />
<button type="submit">更新设置</button>
</form>| 属性 | 用途 | 幂等性 |
|---|---|---|
hx-get | 获取资源 | 幂等 |
hx-post | 创建资源/提交数据 | 非幂等 |
hx-put | 完整替换资源 | 幂等 |
hx-patch | 部分更新资源 | 非幂等 |
hx-delete | 删除资源 | 幂等 |
请求指示器
当网络请求需要时间时,给用户反馈至关重要。htmx 通过 hx-indicator 属性提供了优雅的加载状态显示机制。
基础指示器
<button hx-get="/api/slow-data" hx-indicator="#loading">
加载数据
</button>
<div id="loading" class="htmx-indicator">
加载中...
</div>.htmx-indicator 是一个特殊的 CSS 类。htmx 在请求期间自动为匹配的元素添加 .htmx-request 类,你可以利用这个类控制指示器的显示:
.htmx-indicator {
display: none;
}
.htmx-request .htmx-indicator,
.htmx-indicator.htmx-request {
display: inline;
}使用 CSS 动画
<button hx-post="/api/generate" hx-indicator=".spinner">
生成报告
</button>
<span class="spinner htmx-indicator">⏳</span>更现代化的做法是使用 CSS 动画:
.htmx-indicator {
opacity: 0;
transition: opacity 200ms;
}
.htmx-request .htmx-indicator,
.htmx-indicator.htmx-request {
opacity: 1;
}在触发元素上显示状态
<button hx-get="/api/data"
hx-indicator="this"
class="btn">
获取数据
</button>hx-indicator="this" 表示在请求期间,按钮本身会获得 .htmx-request 类。你可以用它改变按钮样式:
.btn.htmx-request {
opacity: 0.6;
cursor: wait;
}包含额外数据
hx-include
有时候需要包含当前元素之外的表单数据:
<form id="filter-form">
<input type="text" name="category" />
<input type="number" name="min-price" />
</form>
<button hx-get="/api/products"
hx-include="#filter-form"
hx-target="#product-list">
筛选商品
</button>hx-include 会将 #filter-form 中所有字段的值包含到请求中。
hx-vals
添加额外的静态或动态值:
<button hx-post="/api/vote"
hx-vals='{"candidate": "alice", "round": 3}'
hx-target="#result">
投票给 Alice
</button>也可以动态计算值:
<button hx-post="/api/track"
hx-vals="js:{timestamp: Date.now(), path: window.location.pathname}">
记录事件
</button>js: 前缀表示后面的内容是 JavaScript 表达式,在请求时动态求值。
请求头控制
hx-headers
自定义请求头:
<button hx-get="/api/protected"
hx-headers='{"X-API-Key": "secret123"}'
hx-target="#data">
获取受保护数据
</button>内容协商
htmx 默认在请求头中发送 HX-Request: true,让服务器识别这是一个 htmx AJAX 请求:
# Flask 示例:根据请求类型返回不同内容
from flask import request, render_template
@app.route('/profile')
def profile():
user = get_current_user()
if request.headers.get('HX-Request'):
# htmx 请求:返回 HTML 片段
return render_template('profile_partial.html', user=user)
# 普通请求:返回完整页面
return render_template('profile.html', user=user)这是 htmx 应用的经典模式:同一个路由,根据 HX-Request 头返回完整页面或局部片段。
错误处理
hx-confirm
在发送请求前弹出确认对话框:
<button hx-delete="/api/account"
hx-confirm="此操作不可撤销,确定要删除账户吗?"
hx-target="body">
删除账户
</button>监听错误事件
document.body.addEventListener('htmx:response-error', function(evt) {
const xhr = evt.detail.xhr;
console.error('请求失败:', xhr.status, xhr.statusText);
alert('请求失败: ' + xhr.statusText);
});
document.body.addEventListener('htmx:send-error', function(evt) {
console.error('网络错误,无法连接到服务器');
});服务端错误响应
服务端返回非 2xx 状态码时,htmx 会触发错误事件。你也可以返回带有错误信息的 HTML 片段:
@app.route('/api/login', methods=['POST'])
def login():
email = request.form.get('email')
password = request.form.get('password')
if not validate_user(email, password):
return '<div class="error">邮箱或密码错误</div>', 401
return '<div class="success">登录成功!</div>'完整示例:评论系统
<div id="comments">
<div class="comment">第一条评论</div>
</div>
<form hx-post="/api/comments"
hx-target="#comments"
hx-swap="beforeend"
hx-indicator="#comment-spinner"
hx-on::after-request="this.reset()">
<textarea name="content" required placeholder="写下你的评论..."></textarea>
<button type="submit">
发表评论
<span id="comment-spinner" class="htmx-indicator">...</span>
</button>
</form>这个表单演示了多个属性的协同工作:
hx-post— 提交评论到/api/commentshx-target+hx-swap="beforeend"— 将新评论追加到列表末尾hx-indicator— 显示加载状态hx-on::after-request— 请求成功后清空表单
总结
本文涵盖了 htmx 请求发起的基础知识:
hx-get— 获取数据,适合加载内容和搜索场景hx-post— 提交数据,是表单交互的主力hx-put/hx-patch/hx-delete— 完整的 RESTful 方法支持hx-indicator— 请求期间的状态反馈机制hx-include/hx-vals— 灵活控制请求数据HX-Request请求头 — 服务端识别 htmx 请求的经典模式
掌握这些属性后,你已经能够构建大部分常见的 AJAX 交互场景。下一篇文章将深入探讨 目标元素与内容交换策略,理解 hx-target 和 hx-swap 的完整能力。
评论
Written by
AI-Writer
Related Articles
hx-get 与 hx-post 基础请求
深入掌握 htmx 的基本 HTTP 请求属性,学习如何通过声明式 hx-get、hx-post 发起异步请求,以及请求指示器和错误处理机制
Read More