Go+HTMX: web开发降低心智负担的一种选择?

众所周知,一段时间前我一直在关注web开发框架,总的来说,大同小异. 如何进行快速开发小应用,是一个并不简单回答的问题.这里我给出一个解决方案:Go+HTMX.

这两个技术我不过多介绍,htmx顾名思义,在html上封了一层提供与后端交互的功能. 使用Go因为它的简洁且自带GC,不像c++和rust需要仔细小心管理内存,没有选用Java/C#也是因为后两者使用通常都要带上巨大的库(大型库会带来依赖上的安装、管理以及心智负担),在开发小应用时往往没有必要. HTMX主要承担了一部分js的作用.

htmlx只有14k的大小,没有其他依赖,增强了html的功能. 再次说明,我介绍这个技术栈目的是为了快速开发中小应用,如果为了工作或是进一步学习,推荐Java/C#/Go等,再不济也是Python/PHP/Ruby.搭配vue/react/svelte/solid.

关于Go的web开发,常用Gin作为框架,主要写REST API和自带的模板引擎解析html,这里不多赘述.

下面介绍htmx的一些重要功能

HTMX

AJAX

使用html的属性发送请求.

请求方法

AttributeDescription
hx-getIssues a GET request to the given URL
hx-postIssues a POST request to the given URL
hx-putIssues a PUT request to the given URL
hx-patchIssues a PATCH request to the given URL
hx-deleteIssues a DELETE request to the given URL

trigger

通过hx-trigger设置触发动作

1
2
3
<div hx-post="/mouse_entered" hx-trigger="mouseenter">
[Here Mouse, Mouse!]
</div>

可以设置mofiers和filters修改默认行为.

还可以使用轮询

1
2
3
4
5
6
<div hx-get="/news" hx-trigger="every 2s"></div>
<div hx-get="/messages"
hx-trigger="load delay:1s"
hx-swap="outerHTML"
>
</div>

设置indicator表明已经发出请求

1
2
3
4
<button hx-get="/click">
Click Me!
<img class="htmx-indicator" src="/spinner.gif">
</button>
1
2
3
4
5
6
7
8
9
.htmx-indicator{
display:none;
}
.htmx-request .htmx-indicator{
display:inline;
}
.htmx-request.htmx-indicator{
display:inline;
}

当htmx发出请求时,它将把一个htmx-request类放到一个元素上(如果指定,可以是请求元素或另一个元素)。htmx-request类会使带有html-indicator类的子元素的不透明度变为1。

可以设置修改的元素.

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

target

响应默认加载到请求的元素中,可以修改

1
2
3
4
5
6
7
<input type="text" name="q"
hx-get="/trigger_delay"
hx-trigger="keyup delay:500ms changed"
hx-target="#search-results"
placeholder="Search..."
>
<div id="search-results"></div>

swap

htmx提供了几种不同的方法来将返回的HTML交换到DOM.默认情况下,内容会替换目标元素的innerHTML.可以通过使用hx-swap属性来修改这个值:

NameDescription
innerHTMLthe default, puts the content inside the target element
outerHTMLreplaces the entire target element with the returned content
afterbeginprepends the content before the first child inside the target
beforebeginprepends the content before the target in the target’s parent element
beforeendappends the content after the last child inside the target
afterendappends the content after the target in the target’s parent element
deletedeletes the target element regardless of the response
nonedoes not append content from response (Out of Band Swaps and Response Headers will still be processed)

以上就是htmx中Ajax的基本使用,如果知道ajax的运作,那么使用就不会太难.

属性继承

1
2
3
4
5
6
7
8
<div hx-confirm="Are you sure?">
<button hx-delete="/account">
Delete My Account
</button>
<button hx-put="/account">
Update My Account
</button>
</div>

上面两个button继承了hx-confirm的值

1
2
3
4
5
6
7
8
9
10
11
<div hx-confirm="Are you sure?">
<button hx-delete="/account">
Delete My Account
</button>
<button hx-put="/account">
Update My Account
</button>
<button hx-confirm="unset" hx-get="/">
Cancel
</button>
</div>

利用unset取消

增强表单和链接

HTML支持使用hx-boost属性“增强”常规HTML锚和表单.该属性将把所有锚标记和表单转换为AJAX请求,默认情况下,这些请求以页面主体为目标。

1
2
3
<div hx-boost="true">
<a href="/blog">Blog</a>
</div>

这个div中的锚标记将向/blog发出一个AJAX GET请求,并将响应交换到body标记中

配置响应处理

htmx期望对它发出的AJAX请求的响应是HTML,通常是HTML片段(尽管与hx-select标记匹配的完整HTML文档也很有用).然后,HTML将返回的HTML交换到指定目标的文档中,并使用指定的交换策略.
有时您可能不希望在交换中执行任何操作,但仍然可能触发客户端事件.
对于这种情况,默认情况下,您可以返回204 - No Content响应代码,并且html将忽略响应的内容.
在服务器错误响应的事件中(例如404或501),html将触发html:responseerror事件,你可以处理。
如果出现连接错误,将触发html:sendError事件。

1
2
3
4
5
responseHandling: [
{code:"204", swap: false}, // 204 - No Content by default does nothing, but is not an error
{code:"[23]..", swap: true}, // 200 & 300 responses are non-errors and are swapped
{code:"[45]..", swap: false, error:true}, // 400 & 500 responses are not swapped and are errors
]

可以配置下面这些选项:

  • code - a String representing a regular expression that will be tested against response codes.
  • swap - true if the response should be swapped into the DOM, false otherwise
  • error - true if htmx should treat this response as an error
  • ignoreTitle - true if htmx should ignore title tags in the response
  • select - A CSS selector to use to select content from the response
  • target - A CSS selector specifying an alternative target for the response
  • swapOverride - An alternative swap mechanism for the response

配置请求头和响应头

Request Headers

htmx includes a number of useful headers in requests:

HeaderDescription
HX-Boostedindicates that the request is via an element using hx-boost
HX-Current-URLthe current URL of the browser
HX-History-Restore-Request“true” if the request is for history restoration after a miss in the local history cache
HX-Promptthe user response to an hx-prompt
HX-Requestalways “true”
HX-Targetthe id of the target element if it exists
HX-Trigger-Namethe name of the triggered element if it exists
HX-Triggerthe id of the triggered element if it exists

Response Headers

  • HX-Location - allows you to do a client-side redirect that does not do a full page reload
  • HX-Push-Url - pushes a new url into the history stack
  • HX-Redirect - can be used to do a client-side redirect to a new location
  • HX-Refresh - if set to “true” the client-side will do a full refresh of the page
  • HX-Replace-Url - replaces the current URL in the location bar
  • HX-Reswap - allows you to specify how the response will be swapped. See hx-swap for possible values
  • HX-Retarget - a CSS selector that updates the target of the content update to a different element on the page
  • HX-Reselect - a CSS selector that allows you to choose which part of the response is used to be swapped in. Overrides an existing hx-select on the triggering element
  • HX-Trigger - allows you to trigger client-side events
  • HX-Trigger-After-Settle - allows you to trigger client-side events after the settle step
  • HX-Trigger-After-Swap - allows you to trigger client-side events after the swap step

htmx请求的顺序:

  • 元素被trigger
    • 收集需要发送的数据
    • htmx-request类被放在元素上
    • 通过AJAX异步地请求
      • 获得响应后与 htmx-swapping类地内容转换
      • 可选的swap延迟
      • 实际交换内容完成
        • htmx-swapping 类被移除
        • htmx-added 类被添加到每个更改的元素上
        • htmx-settling 类添加到target上
        • 默认延迟
        • DOM完成
        • htmx-settling 被移除
        • htmx-added类被移除

FYI

  1. https://www.youtube.com/watch?v=jeT8m7490Pg
  2. htmx - high power tools for html事实上,htmx是有争议的技术,但不妨碍它依旧很受欢迎
  3. Hello, World - Go语言圣经 (golang-china.github.io)
  4. Get Started - The Go Programming Language (google.cn)
  5. More htmx examples htmx ~ Examples
-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道