htmx - 使 HTML 更強大

‍本文作者是 360 奇舞團開發工程師

htmx

longing for a hypertext

already in hand

這個俳句很有意思,是開源項目htmx文檔中寫的,意思是說,我們已經有了超文本,爲什麼還要去使用 javascript,javascript 的繁瑣,讓人感到疲憊。

目前前端框架很多,但是很多時候我們只是想要一個簡單的功能,比如點擊一個按鈕,然後發送一個請求,然後更新頁面的某個部分,這個時候,我們就不需要一個複雜的前端框架,只需要一個簡單的工具就可以了,這個時候,htmx就是一個很好的選擇。

htmx 是什麼

先來看HTMLHTML的優勢在於,它是一個聲明式的語言,我們可以直接在 html 中聲明我們想要的效果,而不需要去寫 js 代碼,這樣就可以減少很多的代碼量,同時也可以減少很多的 bug。而且,html 是一個很簡單的語言,很多人都可以很快的上手,這樣也可以減少很多的學習成本。

我們先看看HTML的一些限制:

  1. 僅 <a> 和 <form> 發送 HTTP 請求

  2. 僅 clicksubmit 事件觸發 HTTP 請求

  3. 僅 GET 和 POST 方法可以用

  4. 傳統的前端開發中,頁面的更新通常是通過重新加載整個頁面來實現的

htmx讓我們可以在 html 中使用屬性直接訪問 AJAX, CSS Transitions, WebSockets 和 Server Sent Events,用超文本語言來構建現代用戶界面。還有一個消息,2023 年 6 月,htmx進入了 github 加速器扶持的項目的第一序列。

htmx就是利用了這些HTML優勢,解決了HTML的這些限制,讓我們可以在HTML中直接聲明我們想要的效果,而不需要去寫 js 代碼。

htmx 如何實現的

htmx 的實現原理是通過 AJAX、HTML5 和 WebSocket 等技術,將前端和後端的交互方式從傳統的請求 - 響應模式轉變爲增量更新模式,從而實現了無刷新、無跳轉的動態頁面更新。具體來說,htmx 通過在 HTML標籤中添加自定義屬性,如 hx-gethx-posthx-trigger 等,來指定需要執行的 AJAX 請求、響應後的操作以及觸發 AJAX 請求的事件等。在響應返回後,htmx 會根據響應的內容和指定的操作,更新頁面中的部分內容,從而實現了動態更新頁面的效果。此外,htmx 還支持一些高級特性,如服務器推送、表單驗證、動畫效果等,可以幫助開發者更加方便地實現複雜的交互效果。

對了,htmxAJAX請求實現是繼承自intercooler.js

htmx 如何使用

htmx 的安裝

htmx的安裝非常簡單,只需要在HTML中引入htmxcdn地址就可以了,如下所示:

  <script src="https://unpkg.com/htmx.org@1.9.5" integrity="sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO" crossorigin="anonymous"></script>

使用npm安裝的話,只需要執行下面的命令就可以了:

  npm install htmx.org --save

htmx.org是最新版本, htmx是舊版本,不推薦使用。

htmx 的使用

AJAX 請求

htmx可以通過在 html 標籤中添加hx-gethx-posthx-puthx-patchhx-delete屬性來實現 AJAX 請求,如下所示:

  <div hx-get="/time" hx-trigger="every 5s">The time is now: <span hx-swap="outerHTML"></span></div>

上面的代碼中,hx-get屬性指定了請求的 URL,hx-trigger屬性指定了觸發請求的事件,這裏是每 5 秒觸發一次,hx-swap屬性指定了響應返回後,需要更新的內容,這裏是更新span標籤的內容。

htmxAJAX請求觸發事件有很多,如clickinputloadmouseoversubmit等。

<button hx-get="/click" hx-trigger="click">Click Me!</button>

在進行 AJAX 請求時,如何給用戶反饋呢?

htmx提供了hx-indicator屬性,可以指定一個元素,當 AJAX 請求發出時,會在這個元素上添加一個hx-indicator類,當請求返回時,會移除這個類,這樣我們就可以通過 CSS 來實現一些動畫效果,來給用戶反饋。

<div>
    <button hx-get="/click" hx-indicator="#indicator">
        Click Me!
    </button>
    <img id="indicator" class="htmx-indicator" src="/spinner.gif"/>
</div>

另外,如果你希望響應返回後的內容被加載到一個不同於發出請求的元素中,可以使用 hx-target 屬性,該屬性接受一個 CSS 選擇器。通過指定 hx-target 屬性,可以將響應返回的內容加載到指定的元素中,而不是默認的發出請求的元素中。

<input type="text" 
    hx-get="/trigger_delay"
    hx-trigger="keyup delay:500ms changed"
    hx-target="#search-results"
    placeholder="Search..."
>
<div id="search-results"></div>

有了返回的數據,我們可以通過hx-swap屬性來指定如何更新頁面,htmx提供了很多更新頁面的方式,如outerHTMLinnerHTMLafterbeginbeforebeginafterendbeforeend等。

 <!-- this fixed-height div will scroll to the bottom of the div after content is appended -->
  <div style="height:200px; overflow: scroll" 
       hx-get="/example" 
       hx-swap="beforeend scroll:bottom">
     Get Some HTML & Append It & Scroll To Bottom
  </div>

更復雜情況,需要協調兩個元素之間的請求,如何處理呢?例如一個元素的請求能夠取代另一個元素的請求,或者等待另一個元素的請求完成後再發出請求。

htmx 提供了 hx-sync 屬性, 通過指定 hx-sync 屬性,可以將多個元素的請求進行同步,從而實現協調和控制請求的順序和優先級。

<form hx-post="/store">
    <input id="title" 
        hx-post="/validate"
        hx-trigger="change"
        hx-sync="closest form:abort"
    >
    <button type="submit">Submit</button>
</form>

CSS Animations 示例

<style>
  .smooth {
    transition: all 1s ease-in;
  }
</style>
<div id="color-demo" class="smooth" style="color:red"
      hx-get="/colors" hx-swap="outerHTML" hx-trigger="every 1s">
  Color Swap Demo
</div>

在 htmx 中,當從服務器接收到新的內容時,會先檢查頁面中是否存在與新內容中相同 id 屬性的元素。如果找到了匹配的元素,則會將舊內容的屬性複製到新元素上,然後再進行內容的替換。在替換完成後,會有一個 “settle” 延遲(默認爲 20 毫秒),然後再將新屬性值進行替換。這種方式可以讓 CSS 過渡效果在不需要開發者編寫任何 JavaScript 的情況下實現。

htmx還有很多其他的功能,如表單驗證服務器推送WebSocket等,具體可以參考 htmx 文檔,這裏不再一一介紹了。

總結

htmx是一個很好的工具,可以讓我們在不需要寫 js 代碼的情況下,實現很多複雜的功能。但是,通過上述例子也可以發現,爲了實現一些複雜的功能,我們需要在 html 中添加很多屬性,這樣會導致HTML代碼變得很臃腫,不利於維護,所以,htmx的使用場景還是有一定的侷限性的,我們需要根據實際情況來選擇使用。

總之,善於使用工具,才能更好的提高我們的開發效率。

參考資料

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions

https://htmx.org/docs

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/F8vlkiwKhPgJHu5LVo8nbA