历史支持

Htmx 提供了一种与浏览器历史记录 API交互的简单机制:

如果你希望给定元素将其请求 URL 推送到浏览器导航栏并将页面的当前状态添加到浏览器的历史记录中,请包含hx-push-url属性:

<a hx-get="/blog" hx-push-url="true">Blog</a>

当用户点击此链接时,htmx 将快照当前 DOM 并将其存储,然后再向 /blog 发出请求。然后,它会进行交换并将新位置推送到历史堆栈上。

当用户点击后退按钮时,htmx 将从存储中检索旧内容并将其交换回目标,模拟“返回”到之前的状态。如果在缓存中找不到该位置,htmx 将向给定的 URL 发出 ajax 请求,并将标头HX-History-Restore-Request 设置为 true,并期望返回整个页面所需的 HTML。或者,如果 htmx.config.refreshOnHistoryMiss 配置变量设置为 true,它将发出硬浏览器刷新。

注意: 如果你将 URL 推送到历史记录中,则必须能够导航到该 URL 并返回完整页面!用户可以将 URL 复制并粘贴到电子邮件或新选项卡中。此外,如果页面不在历史记录缓存中,则 htmx 在恢复历史记录时将需要整个页面。

指定历史快照元素

默认情况下,htmx 将使用 body 来获取和恢复历史快照。这通常是正确的做法,但如果你想使用更窄的元素来获取快照,则可以使用 hx-history-elt 属性来指定其他元素。

小心:此元素需要出现在所有页面上,否则从历史记录中恢复将无法可靠地进行。

通过第三方库撤销 DOM 变更

如果你正在使用第三方库并想要使用 htmx 历史记录功能,则需要在拍摄快照之前清理 DOM。让我们考虑一下 Tom Select库,它使 select 元素的用户体验更加丰富。让我们设置 TomSelect,将任何具有该类的输入元素变成 .tomselect 丰富的 select 元素。

首先我们需要在新内容中初始化具有该类的元素:

htmx.onLoad(function (target) {
    // find all elements in the new content that should be
    // an editor and init w/ TomSelect
    var editors = target.querySelectorAll(".tomselect")
            .forEach(elt => new TomSelect(elt))
});

这将为所有具有该类的输入元素创建一个丰富的选择器 .tomselect 。但是,它会改变 DOM,我们不希望将该改变保存到历史记录缓存中,因为当历史记录内容重新加载到屏幕时,TomSelect 将被重新初始化。

为了解决这个问题,我们需要捕获 htmx:beforeHistorySave 事件并通过调用它们清除 TomSelect 突变 destroy():

htmx.on('htmx:beforeHistorySave', function() {
    // find all TomSelect elements
    document.querySelectorAll('.tomSelect')
            .forEach(elt => elt.tomselect.destroy()) // and call destroy() on them
})

这会将 DOM 恢复为原始 HTML,从而允许获得干净的快照。

禁用历史快照

通过将当前文档中任何元素或 htmx 加载到当前文档中的任何 html 片段上的 hx-history 属性设置为,可以禁用 URL 的历史记录快照false 。这可用于防止敏感数据进入 localStorage 缓存,这对于共享使用/公共计算机非常重要。历史记录导航将按预期工作,但在恢复时,将从服务器而不是本地历史记录缓存请求 URL。