HTML Invoker Commands来了:以后写弹窗不用再碰JavaScript

摘要:Invoker Commands不是什么能改变世界的大东西,但它把前端开发里最烦人的一件小事给解决了——让按钮控制其他元素,这事本来就应该HTML自己干。以后写代码的时候,遇到按钮控制弹窗这种活,先想想能不能直接用HTML解决。

做前端开发的人都知道,写一个弹窗、一个下拉菜单、一个弹出层,都得这么来:

const button = document.querySelector('#open-btn');
const dialog = document.querySelector('#my-dialog');
button.addEventListener('click', () => {
  dialog.showModal();
});

就为了让按钮点一下把弹窗打开,得写三行JavaScript。这还不算关弹窗的代码。

现在不用了。浏览器新出了一个叫Invoker Commands的东西,直接给HTML按钮加了两个属性,让按钮自己能控制别的元素。点一下按钮打开弹窗、关弹窗、切换菜单,一行JavaScript都不用写

这东西已经在Chrome 135、Firefox 144、Safari 26.2里正式上线了。也就是说,现在你打开浏览器就能用。


核心就两个属性

Invoker Commands给<button>加了两个新属性:

  • commandfor:告诉按钮你要控制谁,填那个元素的ID

  • command:告诉按钮你要干啥,比如打开、关闭、切换

就这么简单。

来看个最直观的例子。以前打开一个对话框要写JS,现在这样就行:

<button commandfor="my-dialog" command="show-modal">
  打开对话框
</button>

<dialog id="my-dialog">
  <p>这个对话框没用一行JS代码就弹出来了</p>
  <button commandfor="my-dialog" command="close">
    关闭
  </button>
</dialog>

点"打开对话框",弹窗出来。点"关闭",弹窗消失。没有JavaScript,没有事件监听,没有DOM查询


目前支持哪些命令

浏览器内置的命令现在有这些:

类型命令作用
Popover(弹出层)toggle-popover切换显示/隐藏
show-popover显示
hide-popover隐藏
Dialog(对话框)show-modal以模态框形式打开
close关闭
request-close请求关闭(会触发cancel事件)

做个弹出菜单试试

以前写这种设置菜单,得写JS控制显示隐藏。现在这样就行:

<button commandfor="settings-menu" command="toggle-popover">设置</button>

<div id="settings-menu" popover>
  <h3>设置菜单</h3>
  <label><input type="checkbox"> 深色模式</label>
  <label><input type="checkbox"> 消息通知</label>
  <label><input type="checkbox"> 自动保存</label>
  <button commandfor="settings-menu" command="hide-popover">完成</button>
</div>

点设置按钮,菜单弹出来。点完成,菜单关上。又是零JS


如果你需要更复杂的功能:自定义命令

内置命令够用大部分场景。但如果你想要自己的命令,比如点按钮让图片翻转,也可以。

自定义命令的规矩:前面加两个破折号--。

<button commandfor="photo" command="--flip-horizontal">
  水平翻转
</button>
<button commandfor="photo" command="--rotate-90">
  旋转90度
</button>

<img id="photo" src="vacation.jpg" alt="照片">

这时候需要写几行JS来接收命令:

document.getElementById('photo').addEventListener('command', (e) => {
  if (e.command === '--flip-horizontal') {
    e.target.style.transform = 'scaleX(-1)';
  } else if (e.command === '--rotate-90') {
    e.target.style.transform = 'rotate(90deg)';
  }
});

注意:command事件是发在被控制的元素上(这里是img),不是按钮上。事件对象里有个e.command,就是你定义的那个命令名。


跟以前的写法有啥不一样

以前控制popover,是用popovertarget和popovertargetaction这两个属性。现在Invoker Commands提供了一个更统一的方式——不管控制dialog还是popover,都用同一套commandfor和command。

而且这两个属性可以跟老的那套共存,你想慢慢迁移也行。


浏览器支持情况

2026年1月,Invoker Commands已经在所有主流浏览器里实现基础支持

  • Chrome:135版本开始支持(2025年4月发布)

  • Firefox:144版本开始支持(2025年10月发布)

  • Safari:26.2版本开始支持(2025年12月发布)

也就是说,现在已经可以在项目里用了


这东西有啥好处

第一,少写很多重复代码。以前每个按钮都要写事件监听,现在直接写在HTML里。对于dialog、popover这种高频组件,能省不少事。

第二,交互不用等JS加载。以前页面刚打开的时候,如果JS还没加载完,点按钮可能没反应。现在HTML自己就能处理交互,首屏体验更好。

第三,无障碍(accessibility)天生就好。屏幕阅读器、键盘导航都支持得不错,不用自己手动加一堆ARIA属性。

第四,Web Components用着更方便。组件作者可以给组件定义一套命令,别人用的时候直接写command="--my-action"就行,不用关心内部怎么实现的。


以后还会支持啥

现在内置命令还不多,主要是popover和dialog。但官方已经在讨论加更多命令了:

  • 媒体控制(播放、暂停)

  • details元素的展开折叠

  • 全屏切换

  • 复制、分享

  • 表单控件控制

Open UI的文档里还提到,以后可能支持<details>的open、close、toggle命令。GitHub上也有讨论说要不要加add-class、toggle-class这种命令。


写在最后

Invoker Commands不是什么能改变世界的大东西,但它把前端开发里最烦人的一件小事给解决了——让按钮控制其他元素,这事本来就应该HTML自己干。

有开发者说得好:"每次Web平台出了新特性,让我们能把实现逻辑往技术栈上游移,我就很兴奋。Invoker Commands就是把按钮点击处理逻辑移到了HTML层"。

以后写代码的时候,遇到按钮控制弹窗这种活,先想想能不能直接用HTML解决。JS应该去处理那些真正复杂的事,基础交互交给浏览器就够了。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_13358