htmx 特性说明

这是一个"特性说明"页面,基于 SQLite 的 "SQLite 中的特性、注意事项和陷阱" 页面

属性继承

htmx 中的许多属性是可继承的:子元素可以从父元素上的属性接收行为。

例如,以下是两个继承自父 div 的目标的 htmx 按钮:

<div hx-target="#output">
    <button hx-post="/items/100/like">点赞</button>
    <button hx-delete="/items/100">删除</button>
</div>
<output id="output"></output>

这有助于避免重复属性,从而保持代码DRY(不重复自己)

另一方面,随着属性与元素距离越来越远,您会失去行为局部性,理解元素行为变得更加困难。

还可能因在父元素上添加属性而无意中改变元素行为。

有些人更喜欢完全禁用 htmx 中的继承,使用 htmx.config.disableInheritance 配置变量

以下是实现此功能的 meta 标签配置:

  <meta name="htmx-config" content='{"disableInheritance":true}'>

默认交换策略是 innerHTML

hx-swap 属性允许您控制交换执行方式。默认策略是 innerHTML,即将响应 HTML 内容放置在目标元素内。

许多人更喜欢使用 outerHTML 策略作为默认值。

您可以使用 htmx.config.defaultSwapStyle 配置变量更改此行为。

以下是实现此功能的 meta 标签配置:

  <meta name="htmx-config" content='{"defaultSwapStyle":"outerHTML"}'>

定位 body 时始终执行 innerHTML 交换

由于历史原因,如果定位 body 元素,htmx 将 始终执行 innerHTML 交换

这意味着您无法通过 htmx 请求更改 body 标签上的属性。

默认情况下 4xx5xx 响应不执行交换

htmx 从不默认交换"错误"状态响应码(400s 和 500s)。

这种行为让一些人感到困扰,特别是某些服务器框架会返回 422 - 无法处理的实体 响应代码来表示表单未正确填写。

初次遇到时可能会非常困惑。

您可以通过 htmx:beforeSwap 事件或通过 htmx.config.responseHandling 配置数组来配置 htmx 的响应行为。

以下是默认配置:

{
  "responseHandling": [
    {"code":"204", "swap": false},
    {"code":"[23]..", "swap": true},
    {"code":"[45]..", "swap": false, "error":true},
    {"code":"...", "swap": false}]
}

注意 204 无内容 也不会被交换。

如果您希望无论响应代码如何都执行交换,可以使用以下配置:

{
  "responseHandling": [
    {"code":"...", "swap": true}]
}

如果您想特别允许 422 响应执行交换,可以使用以下配置:

{
  "responseHandling": [
    {"code":"422", "swap": true},
    {"code":"204", "swap": false},
    {"code":"[23]..", "swap": true},
    {"code":"[45]..", "swap": false, "error":true},
    {"code":"...", "swap": false}]
}

以下是允许所有响应执行交换的 meta 标签:

  <meta name="htmx-config" content='{"responseHandling": [{"code":"...", "swap": true}]}'>

非表单元素的 GET 请求默认不包含表单值

如果非表单元素通过 htmx 发出非 GET 请求(例如 PUT 请求),该元素封闭表单的值(如果有) 将包含在请求中

但是,如果元素发出 GET 请求,封闭表单的值将 不被包含

如果您希望在发出 GET 时包含封闭表单的值,可以使用 hx-include 属性,如下所示:

<button hx-get="/search"
        hx-include="closest form">
  搜索
</button>

历史记录处理可能复杂

htmx 支持与浏览器的历史记录交互。这非常强大,但 也可能很棘手,特别是当您使用修改 DOM 的第三方 JavaScript 库时。

使用 htmx 的历史记录支持时也可能存在安全隐患

大多数问题可以通过禁用任何本地历史缓存并简单地发出服务器请求来解决 当用户向后导航历史记录时,代价是历史导航会更慢。

以下是禁用历史缓存的 meta 标签:

  <meta name="htmx-config" content='{"historyCacheSize": 0}'>

有些人不喜欢 hx-boost

hx-boost 与 htmx 的大多数其他方面相比是一个奇怪的功能:它"神奇地"将 所有锚标签和表单转换为 AJAX 请求。

这可以加快这些交互的感觉,并且允许表单和锚点在 JavaScript 被禁用时继续工作,但它也带来 一些权衡:

htmx 核心团队的某些成员认为,由于这些问题,以及浏览器在页面导航方面已经改进 很多,最好避免使用 hx-boost直接使用未加速的链接和表单

毫无疑问,hx-boost 与其他 htmx 属性相比是个异类,并受到"如果某物能神奇地工作,那么它也能神奇地崩溃"这一格言的影响。

尽管如此,我(Carson)仍然认为它在许多情况下是有用的,并且它被用在 https://htmx.org.cn 网站上。

异步加载 htmx 不可靠

htmx 设计为使用标准的阻塞式 <script> 标签加载,而不是模块延迟加载。 尽管我们尽力尝试在文档生命周期的任何时候加载时初始化 htmx,但某些用例仍会遗漏,通常是涉及 htmx 本身打包或 AJAX 插入的情况。

我们过去的尝试填补这一空白都导致了不可接受的退步。 因此,虽然 htmx 可以异步加载,但风险自负。

另外请记住,如果您的 DOM 内容在 htmx 之前加载,所有 htmx 提供的功能在 htmx 加载前都将无法使用。 预取(甚至"常规"获取)htmx 是解决此问题的一种可能方法。

JavaScript API 不是重点

htmx 是一个面向超媒体的前端库。这意味着 htmx 通过 HTML 中的属性来增强 HTML,而不是提供复杂的 JavaScript API。

确实存在JavaScript API,但它不是库的重点,在大多数情况下, htmx 最终用户不应大量使用。

如果您发现自己大量使用它,特别是 htmx.ajax() 方法,可能 值得问问自己是否有一种更符合 htmx 风格的方法来实现您正在做的事情。