这个包扩展了 Swim HTML DSL,为其添加了 HTMX 的语法糖。

注意:这个包还在开发中 (WIP)。它尚未完成,并且并非所有方面都经过充分考虑。目前请避免在生产环境中使用。 欢迎提交 PR!

HTMX

HTMX 定义了新的 HTML 标签属性,允许任何标签发起网络请求,并用收到的响应替换网站的部分或全部内容。 它开启了从后端驱动丰富 Web 体验的可能性,并在大多数用例中消除了对 React 或 Angular 等浏览器端框架的需求。

HTMX 实现了超媒体的最初承诺,允许构建真正的 RESTful 服务,并减轻了 JavaScript 在前端的繁重工作。

介绍和示例

SwimHTMX 将 HTMX 标签组合到多个函数中,以便在 Swim 中轻松使用。

在下面的 Vapor💧 控制器的示例中,htmxAction 函数应用于一个按钮,定义了:

以及在调用期间禁用按钮。

GET /emoji 端点会响应一个随机的 emoji 文本(这是有效的 HTML),并且每次按下按钮时,<div id:"emoji"> 标签的内容都会被替换为该 emoji 文本。

import Vapor
import SwimHTMX
import SwimVapor
import HTML

struct EmojiController: RouteCollection {

    func boot(routes: RoutesBuilder) throws {
        routes.get("", use: home)
        routes.get("emoji", use: getEmoji)
    }

    func home(req: Request) -> Node {
    
        let emojiDivId = "emoji"

        return html {
            head {
                meta(charset: "utf-8")
                meta(content: "width=device-width, initial-scale=1", name: "viewport")
                script(src: "https://unpkg.com/htmx.org@1.9.10")
                link(href: "css/style.css", rel: "stylesheet")
            }
            body {
                div(class: "center-screen") {

                    div(id: emojiDivId) { "🙂" }

                    button { "Emoji" }.htmxAction(endpoint: .get(path: "/emoji"),
                                                  target: .id(emojiDivId),
                                                  disable: .this)
                }
            }
        }
    }

    func getEmoji(req: Request) async throws -> Node {
        Node.text(String(randomEmoji()))
    }
}

主页被渲染成以下 HTML。 你可以看到包含的 HTMX 属性。

<html>
	<head>
		<meta charset="utf-8"/>
		<meta content="width=device-width, initial-scale=1" name="viewport"/>
		<script src="https://unpkg.com/htmx.org@1.9.10">
		</script>
		<link href="css/style.css" rel="stylesheet"/>
	</head>
	<body>
		<div class="center-screen">
			<div id="emoji">
				🙂
			</div>
			<button hx-disabled-elt="this" hx-get="/emoji" hx-swap="innerHTML" hx-target="#emoji">
				Emoji
			</button>
		</div>
	</body>
</html>

这就是结果: Screen Recording 2024-02-14 at 20 52 11