Volar 是 Vue 3 唯一能正确推导 defineProps、defineEmits 和模板响应式变量类型的语言服务,必须开启 takeOverMode 才能打通 script 与 template 类型链,且需正确配置 files.associations 为 "*.vue": "vue" 并确保 tsconfig.json 存在。

Vue 3 项目里,volar 不只是“能用”,它是唯一能正确推导 defineProps、defineEmits 和模板内响应式变量类型的语言服务。用 vetur 或没启用 takeOverMode,Ctrl+Click 跳转会失效,ref 类型标红、props 补全为空——不是配置漏了,是底层语言服务器根本没接管。
为什么 volar.takeOverMode 必须开
VSCode 默认用 TypeScript 官方语言服务处理 .ts 文件,但对 .vue 文件里的 <script setup></script> 模板上下文一无所知。开启 volar.takeOverMode 后,Volar 才会强制接管整个 TS/JS 语言服务,让 template 中的 {{ count }} 和 script 中的 const count = ref(0) 真正打通类型链。
- 不开这个选项,
defineProps<{ id: number }>()的字段在模板里不会被识别为可访问属性 - 即使写了
emits: ['update:modelValue'],@update:model-value也不会触发自动补全 - 错误提示常卡在 “Cannot find name 'defineProps'”,实际是语言服务没加载 Volar 的 Vue 插件
files.associations 设错会导致 Emmet 失效
如果 .vue 文件被识别为 html(常见于未配或配成 "*.vue": "html"),Emmet 缩写(如 div.flex + Tab)在 <template></template> 内直接不触发;更隐蔽的是,<style lang="scss"></style> 块内也失去 SCSS 语法高亮和片段支持。
- 正确配置是:
"files.associations": { "*.vue": "vue" } - 不要加
"html"或"javascript"关联,那会干扰 Volar 的文件类型判定 - Volar 1.10+ 已默认支持 Emmet,无需额外装插件,但前提是文件类型必须是
vue
自定义代码片段中 $0 和 $1 的位置决定编辑流速
很多 vue.json 片段把光标停在 data() { return { <p>很多 <code>vue.json 片段把光标停在 data() { return { $0 } },看似合理,但实际开发中,90% 的新组件第一行要写的是 props 或 setup(),而不是 data。光标卡在旧范式里,反而打断节奏。
props 或 setup(),而不是 data。光标卡在旧范式里,反而打断节奏。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
立即学习“前端免费学习笔记(深入)”;
- 推荐把
$0放在<script setup lang="ts"></script>的起始标签后,或export default {下一行——这是 Vue 3 的真实入口 - 用
${1:msg}替代裸$1,生成时直接高亮可编辑区域,避免手动删占位符 - 别在
body里写注释行如// 生命周期钩子,它们会随 Tab 展开混进代码,污染 Git diff
插件冲突比想象中更早发生
哪怕只装了 volar 和 eslint,如果 eslint 配置里没禁用 Prettier 规则,保存时就会出现“修复→格式化→再报错”循环:ESLint 把 ref(1) 改成 ref<number>(1)</number>,Prettier 又把它缩回 ref(1),最后光标乱跳、波浪线不消失。
- 必须在
.eslintrc.cjs的extends末尾加上'eslint-config-prettier' - VS Code 设置里关掉
prettier.enable,只留editor.codeActionsOnSave走 ESLint - 卸载
vetur后务必执行Developer: Reload Window,否则 Volar 的语言服务器不会重新注册
最常被忽略的其实是 tsconfig.json —— 没它,@/components/xxx 别名补全、F12 跳转、甚至 defineProps 的泛型推导都会降级。不是插件问题,是 TypeScript 本身没读到路径映射。

















