0

SpringBoo+HTMX编程简介

 1 month ago
source link: https://www.jdon.com/72963.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

SpringBoo+HTMX编程简介

HTMX 是一个小型 JavaScript 库,可让您使用 HTML 中的自定义属性来定义页面中元素的行为。它有点像现代版的 onclick 属性,但功能更强大、更灵活。

它的效率也更高,因为它使用浏览器内置的 HTTP 协议栈来发出请求,而且可以使用浏览器内置的缓存和历史记录管理功能。

它非常适合 Spring Boot 等服务器端框架,因为它允许使用服务器来生成页面的内容和行为,并允许使用浏览器的内置功能来管理导航和历史记录。

HTMX安装
1、最简单的方法是从 CDN 抓取,然后添加到 layout.html 模板中:
<script src='https://unpkg.com/htmx.org/dist/htmx.min.js'></script>

2、使用 Webjar 将库加载到 classpath 中,这样也可以正常工作。Spring 可以做一些额外的事情来帮助浏览器缓存程序库,还可以帮助进行版本管理。见:GitHub (dsyer/webmvc-thymeleaf).

表单处理
我们可以轻松添加的一项功能是使用 HTMX 提交表单,而无需重新加载整个页面。为此,我们可以在表单元素中添加 hx-post 属性:

<form th:action="@{/greet}" method="post" hx-post="/greet">
    <input type="text" name="name" th:value="${name}"/>
    <button type="submit" class="btn btn-primary">Greet</button>
</form>

这将导致 HTMX 拦截表单上的提交操作,并使用 AJAX 请求将数据发送到服务器。服务器将处理请求并返回结果,HTMX 将用结果替换表单内容。

如果不希望结果替换表单内容的效果,可以通过在表单元素中添加 hx-target 属性来解决这个问题:

<form th:action="@{/greet}" th:hx-post="@{/greet}" method="post" hx-target="content">

 "conent"元素:包含ID 和 hx-swap-oob 属性,以实现将传入的内容应替换现有内容:

<div id="content" class="col-md-12" hx-swap-oob="true">
    <span th:text="${greeting}">Hello, World</span><br/>
    <span th:text="${time}">21:00</span>
</div>

这样,HTMX 就提取 "content "元素并为我们切换其内容。图片和其他静态内容不会重新加载,浏览器的历史记录也会更新,以反映页面的新状态。

后端springboot代码:

@PostMapping(path = "/greet")
String name(Map<String, Object> model, @RequestParam String name) {
    greet(model);
    model.put("greeting", "Hello " + name);
    model.put("name", name);
    return "greet";
}

HTMX 在向后端服务器/greet发出的请求中添加了 hx-request 标头:这是 HTMX 的一项功能,可让您在服务器端代码中匹配请求,接下来我们将使用该功能。

使用片段模板
现在,服务器仍会为表单提交重新渲染整个页面,可以通过使用片段模板来提高效率。

在 greet.html 模板中添加 th:fragment 属性:

<div id="content" th:fragment="content" class="col-md-12" hx-swap-oob="true">
    <span th:text="${greeting}">Hello, World</span><br/>
    <span th:text="${time}">21:00</span>
</div>

然后,我们就可以在 SampleController 中的一个新映射方法中使用该片段,该方法仅在请求来自 HTMX 时触发(通过匹配 hx-request 头信息):

@PostMapping(path = "/greet", headers = "hx-request=true")
String nameHtmx(Map<String, Object> model, @RequestParam String name) {
    greet(model);
    return "greet :: content";
}

(":: "语法是 Thymeleaf 的一项功能,可让您呈现模板的片段。例如,找到 "greet "模板,然后查找名为 "content "的片段)。

如果现在提交表单,并查看浏览器开发工具中的网络活动,就会发现服务器只返回了更新内容所需的页面片段。

懒加载
另一种常见用例是在页面首次加载时从服务器加载内容,甚至可以根据用户的偏好进行定制。

我们可以使用 HTMX 来实现这一功能,方法是在要触发请求的元素上添加 hx-get 属性。

我们可以在 layout.html 模板中尝试使用徽标,而不是静态地包含图片。

下面是静态包含图片:

<div class="row">
    <div class="col-12">
    <img src="../static/images/spring-logo.svg" th:src="@{/images/spring-logo.svg}" alt="Logo" style="width:200px;" loading="lazy">
    </div>
</div>

上述代码替换为:

<div class="row">
    <div class="col-12">
    <span class="fa fa-spin fa-spinner" style="width:200px; text-align:center;">
    </div>
</div>

上述代码使用了占位符替换img位置

让 HTMX 动态加载:

<div class="row">
    <div class="col-12" hx-get="/logo" hx-trigger="load">
    <span class="fa fa-spin fa-spinner" style="width:200px; text-align:center;">
    </div>
</div>

注意:这里添加了 hx-get 和 hx-trigger。

  • hx-get 属性告诉 HTMX 向服务器发出 GET 请求,以获取元素的内容。
  • hx-trigger 属性告诉 HTMX 在页面加载时触发请求。默认情况下是在点击时触发。

因此,我们需要在 SampleController 中创建一个新的映射:

@GetMapping(path = "/logo")
String logo() {
    return "layout :: logo";
}

为了只渲染 layout.html 模板中包含图片的片段,必须再次修改 layout.html 模板,使用 th:fragment 属性,替换hx-get和hx-trigger 属性:

<div class="row" th:remove="all">
    <div class="col-12" th:fragment="logo">
    <img src="../static/images/spring-logo.svg" th:src="@{/images/spring-logo.svg}" alt="Logo"
        style="width:200px;" loading="lazy">
    </div>
</div>

请注意,我们必须从模板中th:remove该片段,因为占位符将在初始呈现时替换它。

如果现在运行应用程序,就会看到页面加载时,旋转图标就被真实后端的logo图片取代。

Spring Boot HTMX其他库包
HTMX 还有更多的功能,我们没有时间在此详细介绍。值得一提的是,有一个 Java 库可以帮助实现这些功能,而且还有一些 Thymeleaf 工具:Wim Deblauwe 编写的 Spring Boot HTMX ,可作为 Maven Central 的依赖项。它可以通过自定义注解进行 hx-request 头匹配,还能帮助实现 HTMX 的其他功能。

Unpoly库包
Unpoly的CDN链接是:

<script src='https://unpkg.com/unpoly/unpoly.min.js'></script>

示例代码中的“unpoly”分支和以前一样使用 Webjar。基本(整个页面呈现)表单提交示例如下所示:

<div class="col-md-12">
    <form th:action="@{/greet}" method="post" up-target="content">
    <input type="text" name="name" th:value="${name}"/>
    <button type="submit" class="btn btn-primary">Greet</button>
    </form>
</div>
<div id="content" class="col-md-12">
    <span th:text="${greeting}">Hello, World</span><br/>
    <span th:text="${time}">21:00</span>
</div>

hx-target变成了up-target,其余的 HTMX 装饰只是 Unpoly 中的默认设置。

要转换为片段模板,我们需要遵循 HTMX 中的模式:添加一个th:fragment与 Unpoly 中的唯一标头匹配的控制器方法,例如X-Up-Context。

Hotwired Turbo库包
Hotwired Turbo 的 CDN 链接是:

<script src='https://unpkg.com/@hotwired/turbo/dist/turbo.es2017-umd.js'></script>
示例代码中的“turbo”分支和以前一样使用 Webjar。基本表单提交示例如下所示:

<turbo-frame id="content">
    <div class="col-md-12">
    <form th:action="@{/greet}" method="post">
        <input type="text" name="name" th:value="${name}" />
        <button type="submit" class="btn btn-primary">Greet</button>
    </form>
    </div>
    <div class="col-md-12">
        <span th:text="${greeting}">Hello, World</span><br />
        <span th:text="${time}">21:00</span>
    </div>
</turbo-frame>

Turbo 使用自定义元素 ( turbo-frame) 来标识要替换的内容,而不是标识表单处理交互的自定义​​属性。表格的其余部分不变。

要转换为片段模板,我们需要th:fragment向<turbo-frame>和控制器方法添加一个声明,以匹配来自 Turbo 的唯一标头,例如Turbo-Frame。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK