轻松实现强大的服务器异步通信

HTMX 使得在 Django 等以服务器为中心的 Web 开发框架中,无需 JavaScript 的复杂性即可实现强大的异步功能。在本篇中,我们将通过具体示例,深入探讨 HTMX 处理 Ajax 请求的内部原理以及它与实际 Django 视图的通信方式

htmx的 ajax 通信概念图

HTMX 的核心:HTML 即是消息

传统的 Ajax 通信(例如 axios, fetch)通常从服务器接收 JSON 数据,然后由 JavaScript 解析并重新渲染页面。然而,HTMX 遵循 “Hypermedia as the Engine of Application State (HATEOAS)” 原则。这意味着服务器发送的不是数据 (JSON),而是完整的 HTML 片段,HTMX 只需将其“替换”到指定位置。

HTMX 的 Ajax 通信四步曲

  1. 事件触发: 用户与 HTML 元素(如按钮)进行交互。
  2. Ajax 请求: HTMX 调用浏览器的 fetch API 向服务器发送请求。
  3. HTML 响应: 服务器处理逻辑后,返回的不是整个页面,而是所需的 HTML 片段
  4. DOM 替换 (Swap): HTMX 立即将接收到的 HTML 插入到 hx-target 指定的元素中。

实战示例:“点赞”按钮的实现

我们将不再仅仅是改变数字,而是探讨服务器如何交换 HTML 片段。

1. 前端 (Template)

通过 hx-post 发送请求,并用服务器返回的响应替换整个 #like-section

<div id="like-section">
    <button hx-post="/like/" 
            hx-target="#like-section" 
            hx-swap="outerHTML">
        ❤️ 点赞 ({{ likes_count }})
    </button>
</div>

如本例所示,当 hx-targethx-swap 直接明示在 HTML 标签中时,日后重新阅读代码时,无需翻阅 JavaScript 文件,便能立即了解“点击此按钮后,哪里会如何变化”。个人感觉,虽然查看后端 View 函数可能稍有不便,但像本例这样将 hx- 代码嵌入 HTML 标签中,从 Locality of Behavior 角度来看,或许比内联 JavaScript 更好。

2. 后端 (Django View)

这里重要的一点是,我们使用的是 render 而不是 JsonResponse

from django.shortcuts import render

def like_post(request):
    # 处理点赞逻辑 (例如: DB 更新)
    new_count = 10 

    # 返回一个只包含按钮部分的微小模板片段,而非整个页面。
    return render(request, 'partials/_like_button.html', {
        'likes_count': new_count
    })

3. 响应用的部分模板

这是服务器将传递给客户端的“HTML 片段”。由于设置了 hx-swap="outerHTML",这部分内容将替换掉原有的整个 #like-section

<!-- partials/_like_button.html -->
<div id="like-section">
    <button hx-post="/like/" 
            hx-target="#like-section" 
            hx-swap="outerHTML"
            class="btn-liked">
        ❤️ 点赞 ({{ likes_count }})
    </button>
</div>

为什么要这样做? (原理理解)

在传统方式中,接收到 JsonResponse({'likes': 10}) 后,JavaScript 中需要编写类似 document.getElementById('count').innerText = data.likes 的代码。

然而,HTMX 方式具有以下优点: 1. 防止逻辑碎片化: “点赞后屏幕如何变化”的定义由服务器 (Django 模板) 管理。 2. 数据-视图同步: 服务器发送的 HTML 直接呈现在屏幕上,消除了客户端在处理数据时可能发生的错误。

本期总结

使用 HTMX 不仅仅是减少代码量,更是回归 Web 本源功能——最大限度地利用“超媒体 (HTML)”。通过这种方式,开发者可以摆脱 JavaScript 状态管理的困扰,更专注于服务器端逻辑。

相关文章阅读 :