Web Sockets 扩展可以直接从 HTML 轻松实现与 Web 套接字 服务器的双向通信。这取代了 htmx 以前版本中内置的实验性 hx-ws
属性。有关从旧版本迁移的帮助,请参阅本页底部的 迁移 指南。
¥The Web Sockets extension enables easy, bi-directional communication
with Web Sockets
servers directly from HTML. This replaces the experimental hx-ws
attribute built into previous versions of htmx. For
help migrating from older versions, see the Migrating guide at the bottom of this
page.
使用以下属性配置 WebSockets 的行为方式:
¥Use the following attributes to configure how WebSockets behave:
ws-connect="<url>"
或 ws-connect="<prefix>:<url>"
- 要建立 WebSocket
连接的 URL。
¥ws-connect="<url>"
or ws-connect="<prefix>:<url>"
- A URL to establish a WebSocket
connection against.
可以选择指定前缀 ws
或 wss
。如果未指定,HTMX 默认添加位置的方案类型、主机和端口,以便浏览器通过 websockets 发送 cookie。
¥Prefixes ws
or wss
can optionally be specified. If not specified, HTMX defaults to adding the location’s
scheme-type,
host and port to have browsers send cookies via websockets.
ws-send
- 根据元素的触发值(自然事件或 [hx-trigger
] 指定的事件)向最近的 websocket 发送消息
¥ws-send
- Sends a message to the nearest websocket based on the trigger value for the element (either the natural
event
or the event specified by [hx-trigger
])
¥Installing
安装 ws
的最快方法是通过 CDN 加载它。请记住始终在扩展和 启用扩展 之前包含核心 htmx 库。
¥The fastest way to install ws
is to load it via a CDN. Remember to always include the core htmx library before the extension and enable the extension.
<head>
<script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
<script src="https://unpkg.com/htmx-ext-ws@2.0.2" integrity="sha384-vuKxTKv5TX/b3lLzDKP2U363sOAoRo5wSvzzc3LJsbaQRSBSS+3rKKHcOx5J8doU" crossorigin="anonymous"></script>
</head>
<body hx-ext="ws">
https://unpkg.com/htmx-ext-ws/dist/ws.js 上还有一个未缩小的版本。
¥An unminified version is also available at https://unpkg.com/htmx-ext-ws/dist/ws.js.
虽然 CDN 方法很简单,但你可能需要考虑 在生产中不使用 CDN。安装 ws
的下一个最简单的方法是将其复制到你的项目中。从 https://unpkg.com/htmx-ext-ws
下载扩展,将其添加到项目中的相应目录中,并在必要时使用 <script>
标签将其包含在内。
¥While the CDN approach is simple, you may want to consider not using CDNs in production. The next easiest way to install ws
is to simply copy it into your project. Download the extension from https://unpkg.com/htmx-ext-ws
, add it to the appropriate directory in your project and include it where necessary with a <script>
tag.
对于 npm 样式的构建系统,你可以通过 npm 安装 ws
:
¥For npm-style build systems, you can install ws
via npm:
npm install htmx-ext-ws
安装后,你需要使用适当的工具来打包 node_modules/htmx-ext-ws/dist/ws.js
(或 .min.js
)。例如,你可以将扩展与来自 node_modules/htmx.org/dist/htmx.js
的 htmx 核心和项目特定代码打包在一起。
¥After installing, you’ll need to use appropriate tooling to bundle node_modules/htmx-ext-ws/dist/ws.js
(or .min.js
). For example, you might bundle the extension with htmx core from node_modules/htmx.org/dist/htmx.js
and project-specific code.
如果你使用打包器来管理你的 javascript(例如 Webpack、Rollup):
¥If you are using a bundler to manage your javascript (e.g. Webpack, Rollup):
通过 npm 安装 htmx.org
和 htmx-ext-ws
¥Install htmx.org
and htmx-ext-ws
via npm
将两个包导入到你的 index.js
¥Import both packages to your index.js
import `htmx.org`;
import `htmx-ext-ws`;
¥Usage
<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>
¥Configuration
WebSockets 扩展支持两个配置选项:
¥WebSockets extension support two configuration options:
createWebSocket
- 可用于创建自定义 WebSocket 实例的工厂函数。必须是一个函数,返回 WebSocket
对象
¥createWebSocket
- a factory function that can be used to create a custom WebSocket instances. Must be a function,
returning WebSocket
object
wsBinaryType
- 一个字符串值,定义套接字的 binaryType
属性。默认值为 blob
¥wsBinaryType
- a string value, that defines
socket’s binaryType
property. Default value
is blob
¥Receiving Messages from a WebSocket
上面的示例建立了到 /chatroom
端点的 WebSocket。从 websocket 发送的内容将被解析为 HTML 并由 id
属性交换,使用与 带外交换 相同的逻辑。
¥The example above establishes a WebSocket to the /chatroom
end point. Content that is sent down from the websocket
will
be parsed as HTML and swapped in by the id
property, using the same logic
as Out of Band Swaps.
因此,如果你想更改交换方法(例如,在元素末尾附加内容或将交换委托给扩展),则需要在服务器发送的消息正文中指定。
¥As such, if you want to change the swapping method (e.g., append content at the end of an element or delegate swapping to an extension), you need to specify that in the message body, sent by the server.
<!-- 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>
¥Sending Messages to a WebSocket
在上面的例子中,表单使用 ws-send
属性来指示提交时,表单值应序列化为 JSON 并发送到最近的封闭 WebSocket
,在本例中为 /chatroom
端点。
¥In the example above, the form uses the ws-send
attribute to indicate that when it is submitted, the form values
should be serialized as JSON
and send to the nearest enclosing WebSocket
, in this case the /chatroom
endpoint.
序列化的值将包括一个字段 HEADERS
,其中包含通常随 htmx 请求一起提交的标头。
¥The serialized values will include a field, HEADERS
, that includes the headers normally submitted with an htmx
request.
¥Automatic Reconnection
如果 WebSocket 由于 Abnormal Closure
、Service Restart
或 Try Again Later
意外关闭,此扩展将尝试重新连接,直到重新建立连接。
¥If the WebSocket is closed unexpectedly, due to Abnormal Closure
, Service Restart
or Try Again Later
, this
extension will attempt to reconnect until the connection is reestablished.
默认情况下,扩展使用全抖动 指数退避算法,它会选择随时间呈指数增长的随机重试延迟。你可以通过将其写入 htmx.config.wsReconnectDelay
来使用不同的算法。此函数接受一个参数,即重试次数,并返回重试前等待的时间(以毫秒为单位)。
¥By default, the extension uses a
full-jitter exponential-backoff algorithm that chooses a randomized
retry delay that grows exponentially over time. You can use a different algorithm by writing it
into htmx.config.wsReconnectDelay
. This function takes a single parameter, the number of retries, and returns the
time (in milliseconds) to wait before trying again.
// 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
状态时,该机制将消息保存在内存中,并在连接恢复后发送它们。
¥The extension also implements a simple queuing mechanism that keeps messages in memory when the socket is not in OPEN
state and sends them once the connection is restored.
¥Events
WebSockets 扩展公开了一组事件,允许你观察和自定义其行为。
¥WebSockets extensions exposes a set of events that allow you to observe and customize its behavior.
htmx:wsConnecting
¥Event - htmx:wsConnecting
当尝试建立与 WebSocket 端点的连接时,会触发此事件。
¥This event is triggered when a connection to a WebSocket endpoint is being attempted.
¥Details
detail.event.type
- 事件类型 ('connecting'
)
¥detail.event.type
- the type of the event ('connecting'
)
htmx:wsOpen
¥Event - htmx:wsOpen
当建立了与 WebSocket 端点的连接时,会触发此事件。
¥This event is triggered when a connection to a WebSocket endpoint has been established.
¥Details
detail.elt
- 保存套接字的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that holds the socket (the one with ws-connect
attribute)
detail.event
- 来自套接字的原始事件
¥detail.event
- the original event from the socket
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsClose
¥Event - htmx:wsClose
当与 WebSocket 端点的连接已正常关闭时会触发此事件。你可以通过检查 detail.event
属性来检查事件是否由错误引起。
¥This event is triggered when a connection to a WebSocket endpoint has been closed normally.
You can check if the event was caused by an error by inspecting detail.event
property.
¥Details
detail.elt
- 保存套接字的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that holds the socket (the one with ws-connect
attribute)
detail.event
- 来自套接字的原始事件
¥detail.event
- the original event from the socket
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsError
¥Event - htmx:wsError
当套接字上的 onerror
事件发生时,会触发此事件。
¥This event is triggered when onerror
event on a socket is raised.
¥Details
detail.elt
- 保存套接字的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that holds the socket (the one with ws-connect
attribute)
detail.error
- 错误对象
¥detail.error
- the error object
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsBeforeMessage
¥Event - htmx:wsBeforeMessage
当套接字刚刚收到一条消息时,会触发此事件,类似于 htmx:beforeOnLoad
。此事件在任何处理发生之前触发。
¥This event is triggered when a message has just been received by a socket, similar to htmx:beforeOnLoad
. This event
fires
before any processing occurs.
如果事件被取消,则不会发生进一步的处理。
¥If the event is cancelled, no further processing will occur.
detail.elt
- 保存套接字的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that holds the socket (the one with ws-connect
attribute)
detail.message
- 原始消息内容
¥detail.message
- raw message content
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsAfterMessage
¥Event - htmx:wsAfterMessage
当 htmx 完全处理了一条消息并且所有更改都已确定时,会触发此事件,类似于 htmx:afterOnLoad
。
¥This event is triggered when a message has been completely processed by htmx and all changes have been
settled, similar to htmx:afterOnLoad
.
取消此事件无效。
¥Cancelling this event has no effect.
detail.elt
- 保存套接字的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that holds the socket (the one with ws-connect
attribute)
detail.message
- 原始消息内容
¥detail.message
- raw message content
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsConfigSend
¥Event - htmx:wsConfigSend
当准备从 ws-send
元素发送消息时,将触发此事件。与 htmx:configRequest
类似,它允许你在发送之前修改消息。
¥This event is triggered when preparing to send a message from ws-send
element.
Similarly to htmx:configRequest
, it allows you to modify the message
before sending.
如果事件被取消,则不会发生进一步的处理,也不会发送任何消息。
¥If the event is cancelled, no further processing will occur and no messages will be sent.
¥Details
detail.parameters
- 将在请求中提交的参数
¥detail.parameters
- the parameters that will be submitted in the request
detail.unfilteredParameters
- 在 hx-params
过滤之前找到的参数
¥detail.unfilteredParameters
- the parameters that were found before filtering
by hx-params
detail.headers
- 请求标头。如果不是 falsy,将附加到 HEADERS
属性中的主体
¥detail.headers
- the request headers. Will be attached to the body in HEADERS
property, if not falsy
detail.errors
- 验证错误。如果不为空,将阻止发送并触发 htmx:validation:halted
事件
¥detail.errors
- validation errors. Will prevent sending and
trigger htmx:validation:halted
event if not empty
detail.triggeringEvent
- 触发发送的事件
¥detail.triggeringEvent
- the event that triggered sending
detail.messageBody
- 将发送到套接字的原始消息正文。未定义,可以设置为 WebSockets 支持的任何类型的值。如果设置,将覆盖默认的 JSON 序列化。如果你想使用其他格式(如 XML 或 MessagePack),则很有用
¥detail.messageBody
- raw message body that will be sent to the socket. Undefined, can be set to value of any type,
supported by WebSockets. If set, will override
default JSON serialization. Useful, if you want to use some other format, like XML or MessagePack
detail.elt
- 分派发送的元素(具有 ws-send
属性的元素)
¥detail.elt
- the element that dispatched the sending (the one with ws-send
attribute)
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsBeforeSend
¥Event - htmx:wsBeforeSend
此事件在发送消息前立即触发。这包括来自队列的消息。此时无法修改消息。
¥This event is triggered just before sending a message. This includes messages from the queue. Message can not be modified at this point.
如果事件被取消,消息将从队列中丢弃并且不会发送。
¥If the event is cancelled, the message will be discarded from the queue and not sent.
¥Details
detail.elt
- 分派请求的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that dispatched the request (the one with ws-connect
attribute)
detail.message
- 原始消息内容
¥detail.message
- the raw message content
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
htmx:wsAfterSend
¥Event - htmx:wsAfterSend
此事件在发送消息后立即触发。这包括来自队列的消息。
¥This event is triggered just after sending a message. This includes messages from the queue.
取消事件无效。
¥Cancelling the event has no effect.
¥Details
detail.elt
- 分派请求的元素(具有 ws-connect
属性的元素)
¥detail.elt
- the element that dispatched the request (the one with ws-connect
attribute)
detail.message
- 原始消息内容
¥detail.message
- the raw message content
detail.socketWrapper
- 套接字对象的封装器
¥detail.socketWrapper
- the wrapper around socket object
¥Socket wrapper
你可能会注意到所有事件都公开了 detail.socketWrapper
属性。此封装器包含套接字对象本身和消息队列。它还封装了重新连接算法。它公开了一些成员:
¥You may notice that all events expose detail.socketWrapper
property. This wrapper holds the socket
object itself and the message queue. It also encapsulates reconnection algorithm. It exposes a few members:
send(message, fromElt)
- 安全发送消息。如果套接字未打开,则消息将保留在队列中,并在套接字准备就绪时发送。
¥send(message, fromElt)
- sends a message safely. If the socket is not open, the message will be persisted in the
queue
instead and sent when the socket is ready.
sendImmediately(message, fromElt)
- 尝试发送消息,无论套接字状态如何,绕过队列。可能失败
¥sendImmediately(message, fromElt)
- attempts to send a message regardless of socket state, bypassing the queue. May
fail
queue
- 在队列中等待的消息数组。
¥queue
- an array of messages, awaiting in the queue.
此封装器可用于事件处理程序中,以监视和操作队列(例如,你可以在重新连接时重置队列),以及发送其他消息(例如,如果你想批量发送数据)。fromElt
参数是可选的,当指定时,将在发送消息时触发来自指定元素的相应 websocket 事件,即 htmx:wsBeforeSend
和 htmx:wsAfterSend
事件。
¥This wrapper can be used in your event handlers to monitor and manipulate the queue (e.g., you can reset the queue when
reconnecting), and to send additional messages (e.g., if you want to send data in batches).
The fromElt
parameter is optional and, when specified, will trigger corresponding websocket events from
specified element, namely htmx:wsBeforeSend
and htmx:wsAfterSend
events when sending your messages.
¥Testing with the Demo Server
Htmx 包含一个用 Node.js 编写的演示 WebSockets 服务器,可帮助你查看 WebSockets 的运行情况,并开始引导你自己的 WebSockets 代码。它位于 htmx-extensions
存储库的 /test/ws-sse 文件夹中。查看 /test/ws-sse/README.md 以获取有关运行和使用测试服务器的说明。
¥Htmx includes a demo WebSockets server written in Node.js that will help you to see WebSockets in action, and begin
bootstrapping your own WebSockets code. It is located in the /test/ws-sse folder of
the htmx-extensions
repository. Look at /test/ws-sse/README.md
for instructions on running and using the test server.
¥Migrating from Previous Versions
以前版本的 htmx 使用内置标记 hx-ws
来实现 WebSockets。此代码已迁移到扩展中。以下是迁移到此版本所需采取的步骤:
¥Previous versions of htmx used a built-in tag hx-ws
to implement WebSockets. This code has been migrated into an
extension instead. Here are the steps you need to take to migrate to this version:
旧属性 | 新属性 | 评论 |
---|---|---|
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 服务器的任何子表单 |