Vue3中details标签ToggleEvent无法访问newState/oldState属性问题
问题
在Vue 3.3.4 + TypeScript 5.2项目中使用HTML <details> 标签时,按规范点击该标签应触发ToggleEvent,且事件对象应包含newState和oldState属性,但实际无法获取这两个属性。
示例代码如下:
<template> <details @toggle="onMyToggle"> <summary>My Title</summary> Details.... </details> </template> <script setup lang="ts"> function onMyToggle(e: ToggleEvent) { console.log(e); if (e.newState === "open") { console.log("It's open now!"); } else { console.log("It's closed now!"); } } </script> <style scoped></style>
在Chrome 117和FireFox 118中测试,两个浏览器均宣称支持该事件,Vue已将事件传递给处理函数,但打印的事件对象中缺失newState和oldState属性,控制台输出为:
toggle { target: details, isTrusted: true, srcElement: details, currentTarget: details, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
解决方法
原因分析
目前主流浏览器(包括Chrome、Firefox)虽然支持<details>的toggle事件,但并未实现规范中定义的ToggleEvent接口的newState和oldState属性。浏览器实际触发的只是一个普通的Event对象,而非标准的ToggleEvent。
替代方案
既然无法直接获取newState/oldState,可以通过读取<details>元素的open属性来判断当前状态,有两种实现方式:
方式一:使用Vue的ref获取元素
<template> <details @toggle="onMyToggle" ref="detailsRef"> <summary>My Title</summary> Details.... </details> </template> <script setup lang="ts"> import { ref } from 'vue'; const detailsRef = ref<HTMLDetailsElement | null>(null); function onMyToggle() { if (!detailsRef.value) return; const isOpen = detailsRef.value.open; console.log(isOpen ? "现在展开了!" : "现在收起了!"); } </script> <style scoped></style>
方式二:通过事件目标直接获取状态
无需额外定义ref,直接从事件对象的target属性读取元素状态:
<template> <details @toggle="onMyToggle"> <summary>My Title</summary> Details.... </details> </template> <script setup lang="ts"> function onMyToggle(e: Event) { const detailsEl = e.target as HTMLDetailsElement; const isOpen = detailsEl.open; console.log(isOpen ? "现在展开了!" : "现在收起了!"); } </script> <style scoped></style>
补充说明
ToggleEvent的newState/oldState属性目前仍处于规范草案阶段,尚未被主流浏览器落地实现,这是问题的核心原因。- 直接使用
<details>的open属性是当前最可靠的跨浏览器方案,所有支持<details>的浏览器都支持该属性。
内容的提问来源于stack exchange,提问作者Publius
相关产品推荐
相关产品推荐

