为了账号安全,请及时绑定邮箱和手机立即绑定

使用 HTMX 扩展客户端功能

这篇帖子是一系列比较在客户端实现异步请求的不同方式的文章之一,旨在增强客户端功能性的方法之一。到目前为止,我已经用Vue.jsAlpine.js描述了这种实现方式。从开发者的角度来说,两者都是相似的:两者都涉及到JavaScript。

本文将专注于HTMX,其方式与之不同。

安排工作

我会按照系列之前帖子中的相同结构进行。以下是设置,分别涉及服务器端和客户端。

服务器端

下面,我说明了如何在项目的POM文件中使用Thymeleaf和HTMX:

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>        <!--1-->
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>  <!--1-->
            </dependency>
            <dependency>
                <groupId>org.webjars</groupId>
                <artifactId>webjars-locator</artifactId>                <!--1-->
                <version>0.52</version>
            </dependency>
            <dependency>
                <groupId>org.webjars.npm</groupId>
                <artifactId>htmx.org</artifactId>                       <!--2-->
                <version>2.0.1</version>
                <!--2 使用 htmx.org 是一个用于 HTML 超文本扩展的库,版本为 2.0.1 -->
            </dependency>
    </dependencies>

全屏切换 退出全屏

  1. 和以前的框架一样
  2. HTMX 的依赖

前端

HTML方面的代码很简单。

<script th:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@{/webjars/htmx.org/dist/htmx.js}" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/htmx.org@1.9/dist/htmx.min.js"></script> <!-- 引入 htmx.js 文件 -->

全屏(进入/退出)

  1. 首先,添加 HTMX 依赖
使用 HTMX

我们想实现跟之前一样的功能。

HTMX 实现了一种与传统 AJAX 框架不同的激进方式。它们要求你开发一个接受和返回 JSON 的 HTTP API。而在 HTMX 中,你返回 HTML 片段,这些片段用以替换你配置的 DOM 元素。因此,你既不需要编写 JavaScript,也不需要处理 JSON 和序列化实体。

设计组件

HTMX很好地补充了Thymeleaf,因为它们都处理页面片段。我们可以将Thymeleaf的片段与HTMX的响应对齐。这需要你提前想好,这与以前的AJAX/API/JSON方法不同,但这绝对值得。

让我们列出互动及其替换的片段,比如:

    1. 互动:替换片段1
    1. 互动:替换片段2
    1. 互动:替换片段3

请根据实际情况填写。

  • 加载页面:整个页面是在服务器端渲染的,不是异步加载的。
  • 点击一行中的已完成复选框:该行将被替换为该待办事项的新状态。
  • 清理已完成的任务:将待办事项表格中的已完成行替换为未完成的任务行。
  • 添加新的待办事项:将新待办事项添加到表格中,并将标签字段重置为空白。
  • 添加字段和按钮之前通常放在表格页脚。没有理由改变这一点。

这是我们APP的概念设计的各个部分:

    -------------------- APP --------------------
    | index.html                                |
    |                                           |
    |  ---------------- 表 ----------------  |
    |  | table.html                          |  |
    |  |                                     |  |
    |  |  ------------- 线条 -------------  |  |
    |  |  | lines.html                    |  |  |
    |  |  |                               |  |  |
    |  |  ---------------------------------  |  |
    |  ---------------------------------------  |
    ---------------------------------------------

全屏 退出全屏

我会把HTML页面拆分成这些片段。因为我们是通过Thymeleaf来渲染它们的,所以可以将每个片段拆分到单独的文件中以达到更清晰的分离。在页面首次加载时,我们用Thymeleaf的replace指令;我们用HTMX进行异步客户端交互。

我们第一次的交流

我们先从清理功能开始,因为这是使用HTMX时最简单的功能之一。

这是:
HTML代码:

    <tbody id="lines">...</tbody>                                       <!--1-->

    <button class="btn btn-warning"
            hx-trigger="click"                                          <!--2-->
            hx-delete="/htmx/todo:清理"                                 <!--3-->
            hx-target="#lines">                                        <!--4-->
        清理
    </button>

全屏模式 退出全屏

  1. 定义 lines 这个 DOM 元素
  2. 点击时 HTMX 会被触发
  3. HTMX 会发送一个 DELETE HTTP 请求到相应的 URL
  4. 当 HTML 响应回来时,HTMX 会用新内容替换 lines 元素

请注意,这里没有明确的JavaScript代码,连一行代码都没有。HTMX会处理这些。

服务器这边是这样的,代码就是这样的。

fun htmx(待办事项: MutableList<事项>) = router {
    DELETE("/htmx/todo:cleanup") {  // 删除待办事项
        待办事项.removeIf { 它.完成 }  // 删除已完成的事项
        ok().render("htmx/lines", mapOf("待办事项" to 待办事项))  // 渲染待办事项列表
    }
}

进入全屏 退出全屏

  1. 定期打扫
  2. 使用 render() 函数,而不是 body() 来调用 API。由于我们之前的文件分割,我们现在只需要渲染所需的 HTML 片段。它使用 Thymeleaf 进行必要的服务器端渲染。

HTMX 的精髓就在于,将 HTTP 请求与客户端事件绑定起来,并用服务器的响应来替换特定的 DOM 元素。

添加一个新的待办事项也遵循同样的原则,DOM 元素是整个表格来重置 label 值。如果想了解完整代码,请查看代码

勾选待办事项为已完成

虽然我提到我们不会从检查请求中的情况中退回任何东西,但这带来了一个令人兴奋的挑战。这就是为什么我现在才来处理这个挑战。

点击复选框时,我们遇到了两个问题:

  • 将复选框的状态作为 JSON 数据发送,以在服务器端更新它;
  • 获取并使用 todo 项的 ID。

HTMX 提供了 hx-vals 用于 JSON 数据包。然而,每个行的 URL 都不同,,我们希望在路径中包含 ID,这些 URL 需要在服务器端使用 Thymeleaf 生成。今天我学到了:Thymeleaf 可以处理任何以 th: 开头的 HTML 属性:它会像平常一样处理这个值,然后不加前缀地写入属性名。

    <input type="checkbox"
           th:checked="${todo.completed}"                               <!-- 是否已完成的标志 -->
           hx-trigger="click"                                           <!-- 点击触发事件 -->
           th:hx-patch="'/htmx/todo/' + ${todo.id}"                     <!-- 补丁请求的URL -->
           hx-vals='js:{"checked": event.target.checked}' />            <!-- 设置被选中的值 -->

切换到全屏,退出全屏

  1. 如果 todo 已完成,则使用 Thymeleaf 的常规语法勾选复选框
  2. HTMX 在点击事件上触发
  3. 向服务器发送一个 PATCH 请求,Thymeleaf 会用之前 HTML 中的值替换 id
  4. 静态的请求 JSON 负载

注意,如上所述,我忽略了那个回复。实际上,你应该根据返回的值勾选或取消勾选复选框,以避免服务器状态与UI不同步。

最后

在之前的两篇文章里,我介绍了 Vue 和 Alpine。我们配置了 Spring Boot 以返回 JSON。使用 HTMX,我们让它返回 HTML。此外,我们不需要任何客户端 JavaScript 代码来发送请求。

更妙的是,Thymeleaf 和 HTMX 配合得很好:我们可以将页面拆分成片段并在两边重复使用。

此帖子的完整源代码可在GitHub上找到,网址如下:

GitHub logo ajavageek / 前端对比

示例代码展示,关于 AJAX 和 SSR 的系列文章

更进一步:

zh: 此处省略部分内容

原文发布于A Java Geek,在2024年10月6日。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消