htmx Web Socket 扩展
Web Sockets 扩展可让你直接从 HTML 轻松与 Web Sockets 服务器进行双向通信。这将取代先前版本中内置的实验性属性 hx-wshtmx 。如需从旧版本迁移的帮助,请参阅本页底部的迁移指南。
使用以下属性来配置 WebSocket 的行为方式:
- ws-connect="<url>" 或 ws-connect="<prefix>:<url>"- 用于建立连接的 URL WebSocket。
- 前缀 ws 或 wss 可选指定。如果未指定,HTMX 默认添加位置的方案类型、主机和端口,以便浏览器通过 websockets 发送 cookie。
- ws-send- 根据元素的触发值(自然事件或 [ hx-trigger] 指定的事件)向最近的 websocket 发送消息
安装
<script src="https://unpkg.com/[email protected]/ws.js"></script>
用法
<div hx-ext="ws" ws-connect="/chatroom">
<div id="notifications"></div>
<div id="chat_room">
...
</div>
<form id="form" ws-send>
<input name="chat_message">
</form>
</div>
配置
WebSockets 扩展支持两种配置选项:
- createWebSocket - 可用于创建自定义 WebSocket 实例的工厂函数。必须是一个函数,返回 WebSocket 对象
- wsBinaryType - 一个字符串值,定义套接字的 binaryType 属性。默认值为blob
从 WebSocket 接收消息
上述示例建立了到 /chatroom 端点的 WebSocket。从 WebSocket 发送的内容将被解析为 HTML,并由属性进行交换,使用与带外交换 id 相同的逻辑。
因此,如果你想更改交换方法(例如,在元素末尾附加内容或将交换委托给扩展),则需要在服务器发送的消息正文中指定。
<!-- will be interpreted as hx-swap-oob="true" by default -->
<form id="form">
...
</form>
<!-- will be appended to #notifications div -->
<div id="notifications" hx-swap-oob="beforeend">
New message received
</div>
<!-- will be swapped using an extension -->
<div id="chat_room" hx-swap-oob="morphdom">
....
</div>
向 WebSocket 发送消息
在上面的例子中,表单使用 ws-send 属性来指示在提交时,表单值应该序列化为 JSON 并发送到最近的 WebSocket,在本例中为 /chatroom 端点。
序列化的值将包括一个字段,HEADERS 中包含通常随 htmx 请求一起提交的 HTTP 头。
自动重新连接
如果 WebSocket 因异常关闭、服务重启 或 稍后重试 导致关闭。该插件将尝试重连,直到重新建立连接。
默认情况下,该扩展使用全抖动指数回退算法,该算法选择随时间呈指数增长的随机重试延迟。您可以通过将算法写入 htmx.config.wsReconnectDelay 来使用不同的算法。此函数采用单个参数,即重试次数,并返回重试前等待的时间(以毫秒为单位)。
// example reconnect delay that you shouldn't use because
// it's not as good as the algorithm that's already in place
htmx.config.wsReconnectDelay = function (retryCount) {
return retryCount * 1000 // return value in milliseconds
}
该扩展还实现了一个简单的排队机制,当套接字处于非 OPEN 状态时将消息保存在内存中,并在连接恢复后发送它们。
事件
WebSockets 扩展公开了一组事件,允许你观察和自定义其行为。
事件 - htmx:wsConnecting
当尝试连接 WebSocket 端点时会触发此事件。
detail
- detail.event.type - 事件的类型('connecting')
事件 - htmx:wsOpen
当建立与 WebSocket 端点的连接时触发此事件。
detail
- detail.elt - 保存套接字的元素(具有 ws-connect 属性的元素)
- detail.event - 来自套接字的原始事件
- detail.socketWrapper - 套接字对象的包装器
事件 - htmx:wsClose
当与 WebSocket 端点的连接正常关闭时,会触发此事件。你可以通过检查 detail.event 属性来检查该事件是否由错误引起。
detail
- detail.elt - 保存套接字的元素(具有 ws-connect 属性的元素)
- detail.event - 来自套接字的原始事件
- detail.socketWrapper - 套接字对象的包装器
事件 - htmx:wsError
当套接字上发生 onerror 事件时,会触发此事件。
detail
- detail.elt - 保存套接字的元素(具有 ws-connect 属性的元素)
- detail.error - 错误对象
- detail.socketWrapper - 套接字对象的包装器
事件 - htmx:wsBeforeMessage
当套接字刚刚收到消息时会触发此事件,类似于 htmx:beforeOnLoad。此事件在任何处理发生之前触发。
如果活动被取消,则不会进行进一步的处理。
detail
- detail.elt - 保存套接字的元素(具有 ws-connect 属性的元素)
- detail.message - 原始消息内容
- detail.socketWrapper - 套接字对象的包装器
事件 - htmx:wsAfterMessage
当某条消息完全被 htmx 处理,并且所有更改都已确定时,会触发此事件,类似于htmx:afterOnLoad。
取消此活动没有任何效果。
detail
- detail.elt - 保存套接字的元素(具有 ws-connect 属性的元素)
- detail.message - 原始消息内容
- detail.socketWrapper - 套接字对象的包装器
事件 - htmx:wsConfigSend
准备从 ws-send 元素发送消息时会触发此事件。与 htmx:configRequest 类似,它允许你在发送之前修改消息。
如果事件被取消,则不会发生进一步的处理,也不会发送任何消息。
detail
- detail.parameters - 请求中要提交的参数
- detail.unfilteredParameters - 过滤前找到的 hx-params 参数
- detail.headersHEADERS - 请求头。如果不为 false,则将附加到属性主体中
- detail.errors - 验证错误。如果不为空,将阻止发送并触发 htmx:validation:halted 事件
- detail.triggeringEvent - 触发发送的事件
- detail.messageBody - 将发送到套接字的原始消息正文。未定义,可以设置为 WebSockets 支持的任何类型的值。如果设置,将覆盖默认的 JSON 序列化。如果你想使用其他格式(如 XML 或 MessagePack),则很有用
- detail.elt- 调度发送的元素(具有 ws-send 属性的元素)
- detail.socketWrapper - 套接字对象的包装器
事件 -htmx:wsBeforeSend
此事件在发送消息之前触发。这包括来自队列的消息。此时无法修改消息。
如果事件被取消,消息将从队列中丢弃并且不会发送。
detail
- detail.elt - 发送请求的元素(具有 ws-connect 属性的元素)
- detail.message - 原始消息内容
- detail.socketWrapper - 套接字对象的包装器
事件 - htmx:wsAfterSend
发送消息后立即触发此事件。这包括来自队列的消息。
取消该活动没有任何效果。
detail
- detail.elt - 发送请求的元素(具有 ws-connect 属性的元素)
- detail.message - 原始消息内容
- detail.socketWrapper - 套接字对象的包装器
套接字封装器
你可能会注意到所有事件都公开了 detail.socketWrapper 属性。此封装器保存套接字对象本身和消息队列。它还封装了重新连接算法。它公开了一些成员:
- send(message, fromElt) - 安全地发送消息。如果套接字未打开,则消息将保留在队列中,并在套接字准备就绪时发送。
- sendImmediately(message, fromElt) - 尝试发送消息,不管套接字状态如何,绕过队列。可能会发送失败。
- queue - 队列中等待的一组消息。
此封装器可用于事件处理程序中,以监视和操作队列(例如,你可以在重新连接时重置队列),以及发送其他消息(例如,如果你想批量发送数据)。fromElt 参数是可选的,指定后,将在发送消息时触发来自指定元素的相应 websocket 事件,即htmx:wsBeforeSend 和 htmx:wsAfterSend 事件。
使用演示服务器进行测试
htmx 包含一个用 Node.js 编写的演示 WebSockets 服务器,可帮助你了解 WebSockets 的实际运行情况,并开始引导你自己的 WebSockets 代码。它位于 htmx-extensions 存储库的 /test/ws-sse 文件夹中。查看 /test/ws-sse/README.md 以获取有关运行和使用测试服务器的说明。
从先前版本迁移
以前版本的 htmx 使用内置标记hx-ws来实现 WebSockets。此代码已迁移到扩展中。以下是迁移到此版本所需采取的步骤:
旧属性 | 新属性 | 评论 |
---|---|---|
hx-ws="" | hx-ext="ws" | 使用 hx-ext="ws" 属性将 WebSockets 扩展安装到任何 HTML 元素中。 |
hx-ws="connect:<url>" | ws-connect="<url>" | 向定义扩展的标签添加一个新属性 ws-connect ,以指定你正在使用的 WebSockets 服务器的 URL。 |
hx-ws="send" | ws-send="" | 添加新属性 ws-send 来标记任何应将数据发送到 WebSocket 服务器的子表单 |