輕鬆實現與伺服器間的強大非同步通訊

HTMX 讓您在 Django 這類以伺服器為中心的網頁開發框架中,無需複雜的 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):
    # 處理按讚邏輯 (例如:資料庫更新)
    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 不僅是為了減少程式碼,更是回歸到充分利用網頁本質功能「超媒體 (HTML)」的方式。如此一來,開發者便能擺脫 JavaScript 狀態管理的困擾,更專注於伺服器端邏輯。

相關文章閱讀 :