”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 与 HTMX、WebSockets 和 Hono 聊天

与 HTMX、WebSockets 和 Hono 聊天

发布于2024-08-14
浏览:172

Chat with HTMX, WebSockets and Hono

上周,我写了一篇关于调整 htmx 以显示即时消息的文章。使用 HTMX 一周后,我需要更多。我想要一种更好的方法从服务器流式传输 HTML,使用 JSX 组件而不是纯 HTML 字符串以获得更好的代码可用性。

?温馨提示:如果您觉得有用,请点赞!您的支持帮助我创作更多内容。

我使用的工具:

  • HTMX
  • HTMX Websockets 扩展
  • Hono 后端
  • Websockets - 客户端

这个想法很简单。我的对话组件包装在 hx-ext="ws" 的 div 中,在渲染时连接到我的后端。

export const Conversation = (props: { messages: Message[] }) => (
  
{props.messages.reverse().map((message) => (
))}
);

下一个重要的事情是InputMessageForm。只需将 ws-send 添加到表单中,它就会发送一条消息,其中键是文本区域的 ID (messageInput) 及其值。

export const InputMessageForm = () => (
  
);

Websocket - 服务器

这是 Hono 服务器的完整代码块。一些用于打开和关闭连接的控制台日志。 onMessage 是神奇发生的地方。


get(
    '/chatroom-ws',
    upgradeWebSocket((c) => {
      return {
        onOpen: () => {
          console.log('WS Connection open');
        },
        onClose: () => {
          console.log('WS Connection closed');
        },
        onMessage: async (event, ws) => {
          const { userMessage } = JSON.parse(event.data.toString());
          console.log('Got user message', userMessage);
          const inputArea = await c.html(
            
, ); ws.send(await inputArea.text()); const htmlUser = await c.html(
, ); ws.send(await htmlUser.text()); const response = await talk(userMessage); const htmlAgent = await c.html(
, ); ws.send(await htmlAgent.text()); }, }; }), );

所以流程是:

  1. 接收查询
  2. 空寄回去只是为了让它干净。没有指定 hx-swap-oob,因此默认为 True。这意味着它将找到 id=query-submit-form 的元素并交换它。
  3. 将组件与用户消息一起发送回。这里 hx-swap-oob 被指定为 beforeend ,这仅仅意味着它将被添加到现有消息中。
  4. 谈话→你的逻辑来了。我正在与 AI 助手交谈,以便进行一些外部 API 调用。
  5. 发回带有助理应答的组件。与步骤3相同,但组件不同。

我发现的问题

发回回复有点问题,因为文档是嗯……我认为不太容易理解。甚至创建了一个问题来解决此问题:改进 websocket 扩展的文档。这对我帮助很大!

所以最重要的是:

您需要发回字符串,该字符串解析为与您要交换的内容具有相同 id 的 html!

所以问题。 1

我不小心发回了这样的东西:

JSON.stringify('
test 123
') // '"
test 123
"'

这是错误的。请注意 ID 和转义字符!不要在这里对字符串进行字符串化。

问题编号。 2

您可能认为您可以退回某些东西,并且它会被交换到您想要的地方。不完全是。第一个 div 只是 HTMX 的操作信息。至少我是这样理解的?

我返回这样的html:

仅附加在客户端现有的

内。

最终结果

https://assets.super.so/c0fc84d8-fb32-4194-8758-4be657666aab/videos/c814dcd2-b9e9-4bb2-b8db-2ed9cd7819b7/lucy-chat-example.mov

?这篇文章对您有帮助吗?请发送垃圾邮件“赞”按钮!您的支持非常棒。谢谢!

想了解更多吗?

请继续关注更多见解和教程!访问我的博客?

版本声明 本文转载于:https://dev.to/kuba_szw/chat-with-htmx-websockets-and-hono-bcd?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何在其容器中为DIV创建平滑的左右CSS动画?
    如何在其容器中为DIV创建平滑的左右CSS动画?
    通用CSS动画,用于左右运动 ,我们将探索创建一个通用的CSS动画,以向左和右移动DIV,从而到达其容器的边缘。该动画可以应用于具有绝对定位的任何div,无论其未知长度如何。问题:使用左直接导致瞬时消失 更加流畅的解决方案:混合转换和左 [并实现平稳的,线性的运动,我们介绍了线性的转换。这...
    编程 发布于2025-07-13
  • MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    在两个条件下插入或更新或更新 solution:的答案在于mysql的插入中...在重复键更新语法上。如果不存在匹配行或更新现有行,则此功能强大的功能可以通过插入新行来进行有效的数据操作。如果违反了唯一的密钥约束。实现所需的行为,该表必须具有唯一的键定义(在这种情况下为'名称'...
    编程 发布于2025-07-13
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-07-13
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-07-13
  • 在Ubuntu/linux上安装mysql-python时,如何修复\“ mysql_config \”错误?
    在Ubuntu/linux上安装mysql-python时,如何修复\“ mysql_config \”错误?
    mysql-python安装错误:“ mysql_config找不到”“ 由于缺少MySQL开发库而出现此错误。解决此问题,建议在Ubuntu上使用该分发的存储库。使用以下命令安装Python-MysqldB: sudo apt-get安装python-mysqldb sudo pip in...
    编程 发布于2025-07-13
  • 在JavaScript中如何并发运行异步操作并正确处理错误?
    在JavaScript中如何并发运行异步操作并正确处理错误?
    同意操作execution 在执行asynchronous操作时,相关的代码段落会遇到一个问题,当执行asynchronous操作:此实现在启动下一个操作之前依次等待每个操作的完成。要启用并发执行,需要进行修改的方法。 第一个解决方案试图通过获得每个操作的承诺来解决此问题,然后单独等待它们: co...
    编程 发布于2025-07-13
  • Spark DataFrame添加常量列的妙招
    Spark DataFrame添加常量列的妙招
    在Spark Dataframe ,将常数列添加到Spark DataFrame,该列具有适用于所有行的任意值的Spark DataFrame,可以通过多种方式实现。使用文字值(SPARK 1.3)在尝试提供直接值时,用于此问题时,旨在为此目的的column方法可能会导致错误。 df.withCo...
    编程 发布于2025-07-13
  • Android如何向PHP服务器发送POST数据?
    Android如何向PHP服务器发送POST数据?
    在android apache httpclient(已弃用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    编程 发布于2025-07-13
  • 使用jQuery如何有效修改":after"伪元素的CSS属性?
    使用jQuery如何有效修改":after"伪元素的CSS属性?
    在jquery中了解伪元素的限制:访问“ selector 尝试修改“:”选择器的CSS属性时,您可能会遇到困难。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    编程 发布于2025-07-13
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-07-13
  • 您如何在Laravel Blade模板中定义变量?
    您如何在Laravel Blade模板中定义变量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配变量对于存储以后使用的数据至关重要。在使用“ {{}}”分配变量的同时,它可能并不总是最优雅的解决方案。幸运的是,Blade通过@php Directive提供了更优雅的方法: $ old_section =“...
    编程 发布于2025-07-13
  • Python高效去除文本中HTML标签方法
    Python高效去除文本中HTML标签方法
    在Python中剥离HTML标签,以获取原始的文本表示 仅通过Python的MlStripper 来简化剥离过程,Python Standard库提供了一个专门的功能,MLSTREPERE,MLSTREPERIPLE,MLSTREPERE,MLSTREPERIPE,MLSTREPERCE,MLST...
    编程 发布于2025-07-13
  • Go web应用何时关闭数据库连接?
    Go web应用何时关闭数据库连接?
    在GO Web Applications中管理数据库连接很少,考虑以下简化的web应用程序代码:出现的问题:何时应在DB连接上调用Close()方法?,该特定方案将自动关闭程序时,该程序将在EXITS EXITS EXITS出现时自动关闭。但是,其他考虑因素可能保证手动处理。选项1:隐式关闭终止数...
    编程 发布于2025-07-13
  • Java中Lambda表达式为何需要“final”或“有效final”变量?
    Java中Lambda表达式为何需要“final”或“有效final”变量?
    Lambda Expressions Require "Final" or "Effectively Final" VariablesThe error message "Variable used in lambda expression shou...
    编程 发布于2025-07-13
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-07-13

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3