现代网页用户期待流畅、动态的单页应用 (SPA) 体验。然而,创建 SPA 通常需要 React 和 Angular 等复杂的框架,学习和使用这些框架可能很复杂。htmx 应运而生——它是一个库,通过直接在 HTML 中利用 Ajax 和 CSS 过渡等功能,为构建动态网页体验提供了新的视角。
本指南将探讨 htmx 的功能、它如何简化动态 Web 开发以及如何利用它的潜力来增强您的 Web 开发流程。
在构建交互式 Web 体验时,开发人员传统上有两种主要选择,每种都有其自身的权衡。一方面,有多页应用程序 (MPA),每次用户与之交互时都会刷新整个页面。这种方法确保服务器控制应用程序状态,客户端忠实地表示它。但是,完整的页面重新加载会导致缓慢且笨拙的用户体验。
另一方面,单页应用程序 (SPA) 依赖于在浏览器中运行的 JavaScript 来管理应用程序状态。它们使用 API 调用与服务器通信,API 调用返回数据,通常为 JSON 格式。然后,SPA 使用此数据来更新用户界面而无需页面刷新,从而提供更流畅的用户体验,有点类似于本机桌面或移动应用程序。但是,这种方法也不是完美的。由于大量的客户端处理,计算开销通常更高;初始加载时间可能更慢,因为客户端必须先下载和解析大型 JavaScript 包才能呈现第一页;设置开发环境通常需要处理复杂的构建工具和工作流程。
htmx 为这两种极端情况提供了一种折中方案。它提供了 SPA 的用户体验优势——无需完全页面重新加载——同时保持了 MPA 的服务器端简单性。在此模型中,服务器不是返回客户端需要解释和呈现的数据,而是返回 HTML 片段。然后,htmx 只需替换这些片段即可更新用户界面。
这种方法通过最大限度地减少客户端复杂性以及 SPA 常用的大量 JavaScript 依赖性来简化开发过程。它不需要复杂的设置,并提供流畅且响应迅速的用户体验。
有多种方法可以将 htmx 包含在您的项目中。您可以直接从项目的 GitHub 页面下载它,或者如果您使用的是 Node.js,则可以使用命令 npm install htmx.org 通过 npm 安装它。
但是,最简单的方法(本指南中将使用的方法)是通过内容交付网络 (CDN) 包含它。这允许我们在没有任何设置或安装过程的情况下开始使用 htmx。只需在您的 HTML 文件中包含以下脚本标签:
<code class="language-html"></code>
此脚本标签指向版本 1.9.4,但如果可用较新版本,则可以将“1.9.4”替换为最新版本。
htmx 非常轻量级,最小化和 gzip 版本的重量约为 ~14KB。它没有依赖项,并且与所有主要浏览器兼容,包括 IE11。
将 htmx 添加到您的项目后,您可能需要检查它是否正常工作。您可以使用以下简单示例进行测试:
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container"> Make me laugh! </button> <p id="joke-container">Click the button to load a joke...</p></code>
单击按钮后,如果 htmx 正常工作,它将向 Joke API 发送 GET 请求,并用服务器的响应替换
标签的内容。
htmx 的主要卖点之一是它使开发人员能够通过利用一组不同的属性直接从 HTML 元素发送 Ajax 请求。每个属性代表不同的 HTTP 请求方法:
这些属性接受一个 URL,它们将向该 URL 发送 Ajax 请求。默认情况下,Ajax 请求是由 HTML 元素的“自然”事件触发的(例如,在按钮的情况下为单击事件,或在输入字段的情况下为更改事件)。
考虑以下内容:
<code class="language-html"><button hx-get="/api/resource">Load Data</button></code>
在上面的示例中,按钮元素被分配了一个 hx-get 属性。单击按钮后,将向 /api/resource URL 发出 GET 请求。
服务器返回数据后会发生什么?默认情况下,htmx 将直接将此响应注入到启动元素中——在我们的示例中,是按钮。但是,htmx 不限于此行为,并提供将响应数据指定为目标元素的功能。我们将在接下来的部分中更深入地探讨此功能。
htmx 会响应特定元素上发生的特定事件来启动 Ajax 请求:
让我们通过扩展上面的笑话示例来演示这一点,允许用户搜索包含特定单词的笑话:
<code class="language-html"></code>
要触发搜索,我们需要触发 change 事件。对于 现在结果会立即更新。这很好,但它引入了一个新问题:我们现在正在使用每次按键都进行 API 调用。为了避免这种情况,我们可以使用修饰符来更改触发器的行为。htmx 提供以下内容: 在这种情况下,我们似乎需要 delay: 现在,当您在框中键入内容(尝试使用较长的单词,例如“developer”)时,只有在您暂停或完成键入时才会触发请求。 正如您所看到的,这允许我们仅用几行客户端代码来实现活动搜索框模式。 在 Web 开发中,用户反馈至关重要,尤其是在可能需要花费大量时间才能完成的操作(例如发出网络请求)方面。提供此反馈的一种常见方法是通过请求指示器——指示操作正在进行中的视觉提示。 htmx 集成了对请求指示器的支持,允许我们向用户提供此反馈。它使用 hx-indicator 类来指定用作请求指示器的元素。任何具有此类的元素的不透明度默认为 0,使其不可见但存在于 DOM 中。 当 htmx 发出 Ajax 请求时,它会将 htmx-request 类应用于启动元素。htmx-request 类将导致该元素(或任何具有 htmx-indicator 类的子元素)过渡到不透明度为 1。 例如,考虑一个使用加载微调器作为其请求指示器的元素: 当单击具有 hx-get 属性的按钮并启动请求时,按钮将接收 htmx-request 类。这会导致显示图像,直到请求完成并删除该类。 也可以使用 htmx-indicator 属性来指示哪个元素应该接收 htmx-request 类。 让我们用我们的 Joke API 示例来演示这一点: 注意:我们可以从 CSS 加载器和微调器中获取微调器的 CSS 样式。有很多可供选择;只需单击一个即可接收 HTML 和 CSS。 这将导致在请求进行中时显示加载微调器。 如果我们的网络速度很快,则在发出请求时微调器只会短暂闪烁。如果我们想确保它确实存在,我们可以使用浏览器的开发工具来限制我们的网络连接速度。 或者,仅仅是为了好玩(也就是说,不要在真实的应用程序中这样做),我们可以配置 htmx 来模拟一些网络延迟: 这利用了 htmx 的事件系统,我们可以利用它来修改和增强其行为。在这里,我们使用 htmx:afterOnLoad 事件,该事件在 Ajax onload 完成后触发。我还使用了来自 SitePoint 文章中关于同一主题的 sleep 函数。 这是完成的演示。在框中键入一些内容(例如“JavaScript”),然后在启动请求后观察加载指示器。 正如您所看到的,这允许我们仅用几行客户端代码来实现活动搜索框模式。 在某些情况下,我们可能希望更新与启动请求的元素不同的元素。htmx 允许我们使用 hx-target 属性来定位特定元素以进行 Ajax 响应。此属性可以采用 CSS 选择器,htmx 将使用它来查找要更新的元素。例如,如果我们有一个将新评论发布到我们博客的表单,我们可能希望将新评论附加到评论列表,而不是更新表单本身。 我们实际上在第一个示例中看到了这一点: 按钮不会替换它自己的内容,而是 hx-target 属性声明响应应该替换 ID 为“joke-container”的元素的内容。 htmx 还提供了一些更高级的方法来选择应将内容加载到的元素。这些包括 this、closest、next、previous 和 find。 参考我们之前的示例,我们还可以编写 hx-target="next p" 来避免指定 ID。 默认情况下,htmx 将使用 Ajax 响应替换目标元素的内容。但是,如果我们想附加新内容而不是替换它呢?这就是 hx-swap 属性的用武之地。此属性允许我们指定如何将新内容插入到目标元素中。可能的值是 outerHTML、innerHTML、beforebegin、afterbegin、beforeend 和 afterend。例如,使用 hx-swap="beforeend" 将在新内容添加到目标元素的末尾,这对于我们的新评论场景来说非常完美。 CSS 过渡允许元素的样式从一种状态平滑地更改为另一种状态,无需使用 JavaScript。这些过渡可以像颜色更改一样简单,也可以像完整的 3D 变换一样复杂。 htmx 使在我们的代码中使用 CSS 过渡变得很容易:我们只需要在 HTTP 请求中保持一致的元素 ID。 考虑此 HTML 内容: 在对 /new-content 进行 htmx Ajax 请求后,服务器返回以下内容: 尽管内容发生了变化,但 <input>
元素,当元素的值更改后失去焦点时,就会发生这种情况。因此,在框中键入一些内容(例如“bar”),单击页面上的其他位置,笑话就会出现在 <input>
元素添加 htmx trigger 属性:
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code>
<code class="language-html"><button hx-get="/api/resource">Load Data</button></code>
请求指示器
<code class="language-html"></code>
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code>
<code class="language-html"><button hx-get="/api/resource">Load Data</button></code>
目标元素和内容交换
<code class="language-html"><label for="contains">Keyword:</label>
<input type="text" placeholder="Enter a keyword..." hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#joke-container" name="contains">
<p id="joke-container">Results will appear here</p></code>
扩展 CSS 选择器
内容交换
htmx 中的 CSS 过渡
<code class="language-html"></code>
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code>
<div> 保持相同的 ID。但是,fadeIn 类已添加到新内容中。我们现在可以创建一个 CSS 过渡,该过渡会平滑地从初始状态过渡到新状态:
<pre class="brush:php;toolbar:false"><code class="language-html"><button hx-get="/api/resource">Load Data</button></code></pre>
<p>当 htmx 加载新内容时,它会触发 CSS 过渡,从而创建到更新状态的平滑视觉进度。</p>
<h3>使用视图过渡 API</h3>
<p>新的视图过渡 API 提供了一种在 DOM 元素的不同状态之间进行动画的方法。与 CSS 过渡(涉及更改元素的 CSS 属性)不同,视图过渡是关于对元素的内容进行动画。</p>
<p>视图过渡 API 是一项新的实验性功能,目前正在积极开发中。在撰写本文时,此 API 已在 Chrome 111 中实现,预计更多浏览器将在未来添加支持(您可以在 caniuse 上检查其支持情况)。htmx 提供了一个用于使用视图过渡 API 的接口,并在不支持 API 的浏览器中回退到非过渡机制。</p>
<p>在 htmx 中,有两种使用视图过渡 API 的方法:</p>
<ul>
<li>将 htmx.config.globalViewTransitions 配置变量设置为 true。这将对所有交换使用过渡。</li>
<li>在 hx-swap 属性中使用 transition:true 选项。</li>
</ul>
<p>可以使用 CSS 定义和配置视图过渡。这是一个“弹跳”过渡的示例,其中旧内容弹跳出来,新内容弹跳进来:</p>
<pre class="brush:php;toolbar:false"><code class="language-html"><label for="contains">Keyword:</label>
<input type="text" placeholder="Enter a keyword..." hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#joke-container" name="contains">
<p id="joke-container">Results will appear here</p></code></pre>
<p>在 htmx 代码中,我们在 hx-swap 属性中使用 transition:true 选项,并将 bounce-it 类应用于我们要对其进行动画处理的内容:</p>
<pre class="brush:php;toolbar:false"><code class="language-html">...
hx-trigger="keyup"
...</code></pre>
<p>在此示例中,当 <code><div> 的内容更新时,旧内容将弹跳出来,新内容将弹跳进来,从而产生令人愉悦且引人入胜的视觉效果。
<p>请记住,目前,此演示仅适用于基于 Chromium 的浏览器。</p>
<h2>表单验证</h2>
<p>htmx 与 HTML5 验证 API 很好地集成,如果用户输入验证失败,它将阻止发送表单请求。</p>
<p>例如,当用户单击提交时,只有当输入字段包含有效的电子邮件地址时,才会向 /contact 发送 POST 请求:</p>
<pre class="brush:php;toolbar:false"><code class="language-html"></code></pre>
<p>如果我们想更进一步,我们可以添加一些服务器端验证以确保只接受 gmail.com 地址:</p>
<pre class="brush:php;toolbar:false"><code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code></pre>
<p>在这里,我们添加了一个父元素(div#wrapper),它将自身声明为请求的接收者(使用 this 关键字)并使用 outerHTML 交换策略。这意味着整个 <code><div> 将被服务器的响应替换,即使它不是实际触发请求的元素。我们还在输入字段中添加了 hx-post="/contact/email",这意味着每当此字段模糊时,它都会向 /contact/email 端点发送 POST 请求。此请求将包含我们字段的值。
<p>在服务器端(在 /contact/email),我们可以使用 PHP 进行验证:</p>
<pre class="brush:php;toolbar:false"><code class="language-html"><button hx-get="/api/resource">Load Data</button></code></pre>
<p>如您所见,htmx 期望服务器返回 HTML(<em>不是</em> JSON),然后将其插入到页面中指定的位置。</p>
<p>如果我们运行上面的代码,在输入中键入非 gmail.com 地址,然后使输入失去焦点,则会在字段下方出现一条错误消息,指出“Only Gmail addresses accepted!”</p>
<p><em>注意:当动态地将内容插入 DOM 时,我们还应该考虑屏幕阅读器如何解释此内容。在上面的示例中,错误消息位于我们的标签内,因此屏幕阅读器将在字段下次获得焦点时读取它。如果错误消息插入到其他位置,我们应该使用 aria-describedby 属性将其与正确的字段关联起来。</em></p>
<p>还值得注意的是,htmx 在验证过程中会触发一组事件,我们可以使用这些事件来添加我们自己的验证逻辑和错误处理方法。例如,如果我们想在 JavaScript 代码中实现电子邮件检查,我们可以这样做:</p>
<pre class="brush:php;toolbar:false"><code class="language-html"><label for="contains">Keyword:</label>
<input type="text" placeholder="Enter a keyword..." hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#joke-container" name="contains">
<p id="joke-container">Results will appear here</p></code></pre>
<p>在这里,我们使用 htmx 的 htmx:validation:validate 事件,该事件在调用元素的 checkValidity() 方法之前调用。</p>
<p>现在,当我们尝试使用非 gmail.com 地址提交表单时,我们将看到相同的错误消息。</p>
<h2>htmx 还能做什么?</h2>
<p>htmx 是一个多功能、轻量级且易于使用的工具。它成功地将 HTML 的简单性与通常与复杂的 JavaScript 库相关的动态功能相结合,为创建交互式 Web 应用程序提供了一个引人注目的替代方案。</p>
<p>但是,它不是一个万能的解决方案。对于更复杂的应用程序,您可能仍然需要 JavaScript 框架。但是,如果您的目标是创建快速、交互式和用户友好的 Web 应用程序而无需添加太多复杂性,那么 htmx 绝对值得考虑。</p>
<p>随着 Web 开发的不断发展,htmx 等工具为构建更好的用户体验提供了令人兴奋的新方法。为什么不在未来的项目中尝试一下,看看 htmx 能为您做什么呢?</p>
<h2>关于 HTMX 的常见问题解答 (FAQ)</h2>
<h3>什么是 HTMX,它与其他 UI 设计工具有何不同?</h3>
<p>HTMX 是一个现代的、轻量级的 HTML 扩展,用于 AJAX、CSS 过渡、WebSockets 和服务器发送事件。它允许您直接从 HTML 访问现代浏览器功能,而无需 JavaScript 或 JQuery。这使其与其他 UI 设计工具不同,后者通常严重依赖 JavaScript。HTMX 易于与任何后端集成,并且不需要您重写现有代码。它是增强用户界面的强大工具,同时保持代码简洁且易于维护。</p>
<h3>如何开始使用 HTMX?</h3>
<p>开始使用 HTMX 非常简单。您只需在 HTML 文件中包含 HTMX 脚本即可。完成此操作后,您可以开始在 HTML 标签中使用 HTMX 属性来启用 AJAX、WebSockets 和其他功能。HTMX 网站提供全面的指南和示例,以帮助您入门。</p>
<h3>HTMX 可以与任何后端一起使用吗?</h3>
<p>是的,HTMX 的主要优势之一就是它与后端无关的特性。它可以与任何服务器端语言或框架一起使用。这使其成为在不同环境中工作的开发人员的通用工具。</p>
<h3>HTMX 的一些常见用例是什么?</h3>
<p>HTMX 可用于各种场景,在这些场景中,您希望增强用户界面而无需依赖 JavaScript。这包括表单提交、实时搜索、无限滚动、实时更新等等。它是创建动态、交互式 Web 应用程序的强大工具。</p>
<h3>HTMX 如何处理 CSS 过渡?</h3>
<p>HTMX 内置支持 CSS 过渡。您可以使用“hx-swap”属性来指定在发出请求时元素应如何交换进出。这允许您创建流畅、视觉上吸引人的过渡,而无需编写任何 JavaScript。</p>
<h3>HTMX 与所有浏览器兼容吗?</h3>
<p>HTMX 旨在与所有现代浏览器兼容。但是,因为它使用了一些较新的浏览器功能,所以在较旧或不太常见的浏览器中可能无法完美运行。始终建议在用户可能使用的浏览器中测试您的应用程序。</p>
<h3>HTMX 如何提高 Web 应用程序的性能?</h3>
<p>通过允许您直接从 HTML 访问现代浏览器功能,HTMX 可以大大减少您需要编写的 JavaScript 量。这可以导致更快的加载时间和更高的性能,尤其是在移动设备上,JavaScript 在移动设备上可能特别慢。</p>
<h3>我可以将 HTMX 与我现有的 HTML 和 CSS 一起使用吗?</h3>
<p>是的,HTMX 旨在与您现有的 HTML 和 CSS 一起使用。您无需重写代码或学习新的语言即可开始使用 HTMX。这使其成为增强现有应用程序的绝佳选择。</p>
<h3>HTMX 提供哪种类型的支持?</h3>
<p>HTMX 是一个开源项目,并且有一个充满活力的开发人员社区使用和贡献它。您可以在 HTMX 网站、GitHub 和各种在线论坛上找到帮助和建议。</p>
<h3>如何为 HTMX 项目做出贡献?</h3>
<p>作为一个开源项目,HTMX 欢迎社区的贡献。您可以通过多种方式做出贡献,从报告错误和建议新功能到编写代码和改进文档。查看 HTMX GitHub 页面,了解如何参与。</p>
</div>
以上是HTMX的简介,以HTML为中心的动态UI库的详细内容。更多信息请关注PHP中文网其他相关文章!