- 前端
【免费下载链接】htmx
htmx - high power tools for HTML
htmx 1.8.6(2023-03-02 发布)是 htmx 从"浏览器全局脚本"迈向"现代模块化生态"的关键版本:它首次引入官方 ESM(ECMAScript Modules)构建产物,让开发者可以通过import语句以标准模块方式加载 htmx;同时从 htmx.org 官网构建链中彻底移除了 Sass,使得 Python 2 不再是开发 htmx 的前置依赖。本文基于当前仓库源码与测试,逐项拆解这两个新特性、一个关键 bug 修复(keyup事件的changed修饰符在 Tab 聚焦输入框时失效),并给出可直接运行的实战用法与源码级验证路径。
一、版本背景:1.8.6 在 htmx 演进中的位置
htmx 1.8.x 系列处于 1.x 时代的成熟期,1.8.6 之后仍陆续有 1.8.5、1.8.6 等补丁版本(注意 1.8.6 实际在 1.8.5 之后发布,是 1.8 分支的收尾版本之一),随后项目于 2024 年进入 2.x 时代。当前仓库的 package.json 显示版本已迭代到2.0.11,但 1.8.6 确立的两项技术决策——"发布 ESM 产物"与"官网构建不再依赖 Sass/Python 2"——至今仍是仓库工程化的基石:构建脚本 scripts/dist.sh 至今仍在生成 ESM 产物,官网 www/themes/htmx-theme 也始终以纯 CSS 与静态模板运行。
本次发布公告原文结构清晰,包含两个新特性、两个改进/修复条目。下面逐一深入。
二、新特性一:官方 ESM 支持
2.1 特性意义
1.8.6 之前,htmx 主要以 IIFE(立即执行函数)形式的全局脚本分发,使用方式几乎只有<script src="htmx.min.js"></script>一种。1.8.6 起,官方构建产物中新增ESM 版本,前端工程化项目中可以直接:
<script type="module"> import htmx from 'htmx.org' // 或使用相对路径/本地文件 import htmx from '/path/to/htmx.esm.js' htmx.ajax('GET', '/example', { target: '#target-div' }) </script>2.2 源码实现:ESM 产物如何生成
当前仓库的 scripts/dist.sh 明确展示了 ESM 产物的生成方式——并非手工维护一份独立源码,而是把唯一的源码文件 src/htmx.js 直接包装为 ES 模块:
# Generate ESM script cat > dist/htmx.esm.js << EOF $(cat $HTMX_SRC) export default htmx EOF也就是说,htmx 的全部逻辑始终以一份源码(src/htmx.js)为准,ESM 版只是在末尾追加一行export default htmx。同时该脚本还会生成dist/htmx.js(IIFE)、dist/htmx.min.js、dist/htmx.min.js.gz、dist/htmx.amd.js(AMD)与dist/htmx.cjs.js(CommonJS),覆盖<script>标签、RequireJS、Node/打包器三种主流加载场景。
2.3 工程化配套:类型声明与 IDE 支持
ESM 支持并非孤立存在,它与类型系统、编辑器提示紧密配套:
- 类型声明文件 src/htmx.esm.d.ts 为 TypeScript 项目提供完整的
htmx类型(当前仓库中htmx.esm.d.ts由npm run types-generate从源码生成)。 - JetBrains 系 IDE 的 web-types 元数据由 scripts/generate-web-types.mjs 生成,产物为 editors/jetbrains/htmx.web-types.json,让
hx-*属性在 IDE 中具备自动补全与校验。 - package.json 中
main、types、jsdelivr、unpkg字段分别指向dist/htmx.esm.js、dist/htmx.esm.d.ts与dist/htmx.min.js——从 2.0.1 起main正式指向 ESM 产物,说明 1.8.6 开创的 ESM 路径最终成为 htmx 的主分发入口。
2.4 从 1.8.6 到当前的演进
1.8.6 首次提供dist/htmx.esm.js,让 Vite、Webpack、Rollup 等构建工具可以直接import htmx from 'htmx.org'并参与 tree-shaking 与模块依赖分析;到了 2.0.1,dist/htmx.esm.js更被提升为包入口main文件,这意味着现代打包器默认就会解析到 ESM 产物。可以说 1.8.6 是 htmx 完成"模块化转身"的起点。
三、新特性二:官网构建链移除 Sass,Python 2 不再是开发前提
3.1 背景
htmx.org 官网(即本仓库的 www 目录,基于 Zola 静态站点生成器)早期使用 Sass 预处理器编写样式,而构建 Sass 需要 Ruby 环境;在部分老旧工具链下甚至牵扯到 Python 2。1.8.6 起,网站样式被改为纯 CSS,整个网站构建不再依赖 Sass,Python 2 随之从开发依赖中消失,大幅降低了参与 htmx 开发的门槛。
3.2 当前仓库中的实际形态
查看 www/themes/htmx-theme 主题目录可以看到:
- 样式文件为纯 CSS:www/themes/htmx-theme/static/css/site.css,仓库中不存在任何
.scss/.sass源文件; - 网站运行时所需的 htmx 脚本直接来自源码拷贝——scripts/www.sh 会把 src/htmx.js 复制为 www/themes/htmx-theme/static/js/htmx.js,保证官网演示与仓库源码始终同步;
- 该脚本还会把
test/与src/同步到 www/static,使官网可以直接运行浏览器测试套件。
这一改动让 htmx 的"源码→构建→官网演示→测试"链条全部收敛到 Node.js + bash 之上。当前 package.json 的脚本(npm run dist、npm run www、npm run test等)已完全不需要 Python 2,与 1.8.6 的决策一脉相承。
四、关键 Bug 修复:keyup的changed修饰符在 Tab 聚焦时失效
4.1 问题描述
hx-trigger支持changed修饰符,其语义为"仅当元素的值相对于上一次触发时发生了变化,才发起请求"。1.8.6 修复了一个边界 bug:当输入框是通过键盘 Tab 键聚焦(tabbed into)时,keyup changed组合无法正确判断值变化,导致请求被错误地触发或漏触发。
4.2 源码级原理:changed修饰符如何工作
当前 src/htmx.js 中的实现分为两个阶段:
阶段一:触发规范解析。在解析hx-trigger字符串时,遇到changedtoken 即给该触发规范打上标记(src/htmx.js):
if (token === 'changed') { triggerSpec.changed = true }阶段二:值快照与比对。htmx 在addEventListener绑定监听器时,会为每个被监听元素记录当前value作为基准快照(src/htmx.js),使用嵌套的WeakMap按触发规范隔离存储,避免不同 triggerSpec 相互干扰:
if (triggerSpec.changed) { if (!('lastValue' in elementData)) { elementData.lastValue = new WeakMap() } eltsToListenOn.forEach(function(eltToListenOn) { if (!elementData.lastValue.has(triggerSpec)) { elementData.lastValue.set(triggerSpec, new WeakMap()) } elementData.lastValue.get(triggerSpec).set(eltToListenOn, eltToListenOn.value) }) }事件触发时(src/htmx.js),取出evt.target.value与快照比较,相同则直接 return(不发起请求),不同则更新快照:
if (triggerSpec.changed) { const node = evt.target const value = node.value const lastValue = elementData.lastValue.get(triggerSpec) if (lastValue.has(node) && lastValue.get(node) === value) { return } lastValue.set(node, value) }可以推断,1.8.6 之前的 bug 与"值快照的初始化时机/来源元素判定"有关:Tab 聚焦路径下事件目标与快照记录的元素不一致或快照未正确初始化,导致changed判定失效。修复后无论用户是点击进入输入框还是 Tab 聚焦,快照比对都保持一致。
4.3 测试验证:changed修饰符的回归保护
当前仓库的 test/attributes/hx-trigger.js 为changed修饰符提供了多组用例,其中 test/attributes/hx-trigger.js 的核心用例完整覆盖了"值未变不请求、值变化才请求、再次点击不重复请求"的行为:
it('changed modifier works', function() { // ... 模拟点击 input input.click(); this.server.respond() div.innerHTML.should.equal('') // 值未变:无请求 input.value = 'bar' input.click(); this.server.respond() div.innerHTML.should.equal('Requests: 1') // 值已变:发起请求 input.click(); this.server.respond() div.innerHTML.should.equal('Requests: 1') // 值未再变:不再请求 })仓库还覆盖了与from:子句组合、多输入框、多 triggerSpec 隔离等场景(test/attributes/hx-trigger.js),确保这一修复不会破坏既有行为。
五、实战:changed修饰符的典型用法
5.1 标准修饰符速查
hx-trigger的标准修饰符(完整定义见 www/content/attributes/hx-trigger.md):
| 修饰符 | 作用 |
|---|---|
once | 事件只触发一次(如首次点击) |
changed | 仅当元素值发生变化时才触发(注意change是事件名,changed是修饰符名,二者不同) |
delay:<时间> | 事件触发前延迟,期间再次触发则重置计时 |
throttle:<时间> | 事件触发后节流,节流期间再次触发被忽略 |
from:<选择器> | 监听其他元素的事件(如from:input、from:document、from:closest div) |
target:<选择器> | 按事件目标过滤 |
5.2 搜索框防抖示例
官方文档 www/content/attributes/hx-trigger.md 给出的经典组合——changed搭配delay,实现"输入变化且停顿 1 秒后才搜索":
<input name="q" hx-get="/search" hx-trigger="input changed delay:1s" hx-target="#search-results"/>响应内容会被插入到id="search-results"的元素中。changed保证"连续输入同一值不重复请求",delay:1s保证"输入停顿后才请求",两者结合正是防抖搜索的标准范式。
六、如何在本仓库中验证 1.8.6 的两项遗产
当前仓库可以直接复现/验证上述机制:
- 查看 ESM 构建:执行
npm run dist(由 scripts/dist.sh 驱动,先运行npm install安装依赖),即可在dist/下生成htmx.esm.js等全部产物;源码产物逻辑见 scripts/dist.sh。 - 运行
changed修饰符测试:执行npm run test:chrome(依赖 Playwright,详见 package.json),测试套件中的 test/attributes/hx-trigger.js 会覆盖changed修饰符的完整行为矩阵。 - 观察官网构建链:执行
npm run www(scripts/www.sh)可看到网站如何将 src/htmx.js 同步为官网静态资源——全程无需 Python 2 与 Sass。
七、总结
htmx 1.8.6 表面上是 1.x 时代的一个小版本,却承载了三项影响深远的变更:
- ESM 支持让 htmx 进入现代模块化前端工具链,为后续 2.x 将 ESM 设为包入口(见 package.json 的
main字段)铺平道路; - 移除 Sass / Python 2 依赖让官网构建与整体开发环境回归"纯 Node + bash",降低贡献门槛;
keyup changed聚焦 bug 修复完善了hx-trigger修饰符在键盘导航场景下的可靠性,其修复逻辑至今保留在 src/htmx.js 的值快照机制中,并有 test/attributes/hx-trigger.js 的完整测试守护。
对于使用 htmx 的开发者,1.8.6 最直接的收获是:你可以在构建工具中原生import htmx,同时放心地在输入类元素上使用changed修饰符,无论用户用鼠标还是 Tab 键聚焦,行为都一致可靠。
- 前端
【免费下载链接】htmx
htmx - high power tools for HTML
相关推荐
Gatsby v5.10.0 发布说明解析:SSR/DSG 引擎瘦身、Drupal/Contentful typePrefix 支持与构建稳定性修复
Gatsby v5.10.0 发布说明解析:SSR/DSG 引擎瘦身、Drupal/Contentful typePrefix 支持与构建稳定性修复 本篇文章围
前端静态站点Web框架CommandAPI Kotlin DSL:用Kotlin编写Minecraft命令的完全指南
CommandAPI Kotlin DSL:用Kotlin编写Minecraft命令的完全指南 CommandAPI 是专为 Bukkit/Spigot 服务器
Eclipse Mosquitto 1.5.7 发布详解:Broker 持久化瘦身、include_dir 排序与库 API 修复
Eclipse Mosquitto 1.5.7 发布详解:Broker 持久化瘦身、include_dir 排序与库 API 修复 本篇文章基于 Mosquit
物联网消息队列后端网络/通信
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考