🧠没找到 @vue:mounted?揭秘这个“魔法指令”的前世今生!

289 阅读2分钟

一、故事开始:我以为我不懂 Vue,后来发现是我太懂了

某天下午,团队在重构一个 Vue3 项目,我在 Review 同事 PR 时,眼前一亮:

<script setup>
defineExpose({
  '@vue:mounted': () => {
    console.log('组件被挂载了!')
  }
})
</script>

我当场懵住:@vue:mounted?Vue3 官方文档里根本没见过这个写法啊!

Google、Vue 官网、GitHub issues 都翻遍了,愣是没找到解释。

是我脱离社区太久了吗?还是我同事在用什么黑科技?

——于是,我开始了这场“破案之旅”。


二、真相浮出水面:这不是你熟悉的 mounted

我们熟悉的 Vue 生命周期,在 <script setup> 中通常这样写:

onMounted(() => {
  console.log('组件挂载完毕')
})

@vue:mounted 是什么?

答案是:这是一种 DevTools 用的调试钩子,不是正式 API。

重点来了:它是 Vue DevTools 和调试工具注入的一种 内置调试 hook,用于追踪生命周期或组件状态,而不是供开发者主动调用的 API。


三、它从哪儿来的?这才是真正的幕后黑手

这个写法的根源来自 Vue 插件的调试 API(如 devtools hook、宏指令 transform) 。通常以下几种场景可能看到它:

  • 插件作者通过 defineExpose 暴露内部方法供 DevTools 追踪
  • 在一些低层框架(如 Vite 插件、unplugin 系列)中注入调试钩子
  • Vue SFC Playground 或 Nuxt Devtools 中也会生成类似结构

你可以理解为:

@vue:* 是 Vue DevTools 为了能在组件树中更好地追踪生命周期和行为而设置的“隐秘通道”。


四、能用在项目中吗?不建议!除非你是 DevTools 作者

这段代码虽然不会报错,但不建议业务代码中使用,原因有三:

  1. 不是文档公开 API,未来版本可能随时变动或废弃
  2. 不是为开发者使用设计的,而是为调试工具准备的
  3. 会增加阅读成本,影响代码清晰性

更标准的写法应为:

import { onMounted } from 'vue'

onMounted(() => {
  console.log('组件加载完成')
})

五、那 defineExpose 到底该怎么用?

defineExpose<script setup> 的语法糖,用于将内部逻辑暴露给外部使用(比如父组件 ref 调用)。

例如:

<script setup>
function scrollToBottom() {
  // ...
}
defineExpose({ scrollToBottom })
</script>

外部组件可通过 ref 使用:

<MyComponent ref="compRef" />
compRef.value.scrollToBottom()

⚠️ 所以 @vue:mounted 并不是官方推荐的 expose 内容,只是调试时内部使用的注入项。


六、尾声:魔法的尽头,是理解底层

这件小事提醒了我:

当你看到一些“非主流”的代码写法,先别急着 Google,先从源码、插件、调试工具入手,可能能发现意想不到的内幕。

“@vue:mounted”不是错,它只是不是给你用的

希望这篇文章,能帮你和你的同事少走点弯路,也能激发你对 Vue 生态更深层的探索欲望。


📎附录:相关延伸阅读