文章摘要
文章探讨了在HTMX中使用URL参数作为应用状态的单一来源,以实现可书签、可分享的应用状态管理。通过将过滤、排序、分页和搜索等状态信息嵌入URL,用户可以在不丢失上下文的情况下进行书签、分享或刷新页面。文章还介绍了实现这一模式的三个关键步骤:服务器读取URL参数并渲染视图、表单和HTMX请求保留所有状态、浏览器URL自动更新。这种方法简化了状态管理,无需额外依赖。
文章总结
标题:通过设计实现可书签化:HTMX中的URL驱动状态 | Loren Stewart
主要内容:
在从React转向HTMX时,开发者将复杂的状态管理替换为服务器端的简洁性。然而,仍然需要处理过滤、排序、分页和搜索等功能。那么,这些状态现在应该存放在哪里呢?
答案非常优雅:存放在URL本身。通过将URL参数视为单一的真实来源,开发者可以获得可书签化、可共享的应用程序状态,而无需安装额外的依赖。
模式实践:
例如,URL /?status=active&sortField=price&sortDir=desc&page=2 可以完整地描述当前视图。它不仅仅是一个地址,而是一个完整的状态表示,用户可以将其书签化、分享或刷新而不会丢失上下文。
快速入门:三个关键步骤:
- 服务器读取URL参数并渲染相应的视图。
- 表单和
hx-include在发起HTMX请求时保留所有状态。 - 浏览器URL通过
hx-push-url自动更新。
步骤1:服务器读取URL状态:
服务器端点读取查询参数并使用它们来渲染初始视图。例如,通过解析sortField、sortDir、status和page等参数,服务器可以应用这些状态来查询数据,并将结果返回给模板进行渲染。
步骤2:表单和隐藏字段保留状态:
在HTML模板中,表单通过隐藏字段保留当前状态,确保在用户进行过滤或排序操作时,所有状态都能被保留并传递给服务器。
步骤3:通过hx-push-url自动同步URL:
使用hx-push-url="true"和hx-params="*",HTMX会自动处理URL的更新,将所有表单数据作为查询参数发送到服务器,并更新浏览器URL,同时创建适当的历史记录条目,以便用户可以通过浏览器的后退/前进按钮导航。
生产环境考虑:
- URL长度限制:浏览器通常支持最多约2000个字符的URL,对于复杂的过滤条件,可以考虑使用缩写参数名称或将部分状态移至服务器端。
- 参数验证:始终在服务器端验证和清理URL参数,将其视为不可信的用户输入。
- 测试:由于状态明确地存在于URL和表单值中,这种模式非常易于测试,无需模拟复杂的JavaScript函数。
架构优势:
这种以URL为先的方法带来了多重好处,而无需复杂的客户端状态管理库。每个视图都是可共享的,用户可以将链接发送给同事,对方将看到完全相同的内容。浏览器的后退按钮可以按预期工作,返回之前的过滤状态。SEO也得到了内置支持,因为搜索引擎可以爬取每个状态组合。调试体验透明,因为当前状态始终显示在地址栏中。
通过将URL作为状态存储,开发者不仅是在利用Web平台,而且是在与其协同工作。这种模式从简单的排序扩展到复杂的多过滤界面,同时保持了HTMX最初的简洁性。
结论:
下次当开发者考虑使用状态管理库时,不妨思考一下,是否URL已经足够。在许多情况下,URL不仅足够,而且更为优越。
评论总结
评论主要围绕URL作为状态管理的核心展开,观点多样且具有争议性。以下是总结:
支持URL作为状态管理的观点: 1. URL作为状态管理的优势:多位评论者认为将状态存储在URL中是一种经典且有效的模式,尤其适用于书签和分享功能。例如,PaulHoule提到这是1990年代Web应用的经典模式,而heimdall强调理解URL的工作原理对支持深度链接非常重要。 - "This is a classic pattern of web applications from the 1990s." (PaulHoule) - "Learning why URLs work the way they work is still extremely useful." (heimdall)
- URL的灵活性和扩展性:o11c指出可以通过
location.hash存储更长的状态,而Twey建议使用唯一ID来确保URL的可书签性。- "Note that you can store longer state in the fragment (
location.hash)." (o11c) - "To get truly bookmarkable list URLs, the best approach is ‘page starting from item X’." (Twey)
- "Note that you can store longer state in the fragment (
反对或质疑URL作为单一状态源的观点: 1. 状态管理的复杂性:btown认为URL不能作为单一的状态源,因为UI的状态分为“进行中”、“已提交”和“已加载”三种,不同应用场景需要不同的处理方式。 - "Hard disagree that there can be a single source of truth." (btown) - "One size does not fit all." (btown)
- 框架和工具的不足:DimmieMan批评现有框架对URL参数处理的支持不足,认为开发者花费大量时间处理异步请求,而框架却缺乏对URL参数的友好支持。
- "Huge amount of dev time spent being able to execute asynchronous functions to the backend seamlessly." (DimmieMan)
- "Even tools like sveltekit have next to zero support." (DimmieMan)
其他相关观点: 1. 工具和库的推荐:cadamsdotcom建议将URL状态管理封装为React钩子,而cloudking推荐使用Alpine.js作为轻量级的React替代方案。 - "Does something like this exist?" (cadamsdotcom) - "Alpine.js is pretty powerful and capable for building reactive SPAs." (cloudking)
- 历史与创新:TimTheTinker回顾了早期使用jQuery和ExtJS时通过
location.hash管理状态的经验,而rorylaitila提出了在HTMX中使用“sync-params”来同步页面链接状态的用例。- "Just read from location.hash during page load and write to it when the form state changes." (TimTheTinker)
- "In my progressive enhancement library I call this ‘sync-params’." (rorylaitila)
总结:URL作为状态管理的核心有其优势,尤其在书签和分享功能上表现突出,但也存在复杂性和框架支持不足的问题。开发者应根据具体需求选择合适的工具和策略。