先给结论:Vue 文件失去智能提示,九成是两个 Vue 扩展同时启用、或者语言服务没找到项目的 tsconfig。修起来不需要重装编辑器,按顺序确认四件事——当前启用的扩展是否只有一个提供 Vue 语言服务、是否开了 takeover 模式、项目根目录有没有配置文件、打开文件的工作区是不是项目根目录本身。

新手的常见反应是反复重启 VS Code,或者把插件卸了重装。这两步偶尔有用,但没解决根因时会反复发作:今天好了,明天换个项目打开又没了。因为根因通常在工程这一侧,而不是编辑器。
本文基于 VS Code 加 Vue 3 项目的通用配置实践,涉及 Volar、Vetur 与 TypeScript 语言服务的协作方式。所有命令的输出均为预期结果(未在本机执行),读者需要照着跑一遍确认。适用边界也写清楚:纯 JavaScript 的 Vue 2 老工程与 TypeScript 新工程的正确配置并不相同。
先看结论
- 二选一:提供 Vue 语言服务的扩展只留一个,Vue 3 工程用 Vue Language Features(Volar),混用会互相抢占。
- 开 takeover 模式:让 Volar 接管 TypeScript 的语言服务,避免两套服务给出不同补全。
- 补配置文件:项目根目录要有 tsconfig.json 或 jsconfig.json,且 include 要覆盖源码目录。
- 用根目录打开:直接在项目根打开工作区,打开父目录会让语言服务找不到配置。
Vue 文件自身的结构与语法细节,可以对照 Vue3 教程 里的单文件组件章节过一遍。
一、先确认是不是扩展打架
第一步是看扩展列表,把提供 Vue 语言服务的插件清点干净:
code --list-extensions
预期输出(未在本机执行)是一串形如 publisher.extension 的 id 列表。重点关注两类:名字里含 volar / vue-language-features 的,以及名字里含 vetur 的。
判断规则按项目版本分:
- Vue 3 工程:保留 Vue Language Features(Volar),把 Vetur 禁用;
- Vue 2 老工程:历史上用 Vetur 提供.template 的补全,迁移到 Volar 需要额外适配,不要两边都留;
- 两个都没装:自然没有任何 Vue 语言能力,症状是完全没有提示而不是提示不准。
"扩展打架"的典型表现是:模板里有提示但 script 里没有,或者补全列表里出现两个重复的候选项。这是因为两套服务在同一个文件上各算各的,谁先返回用谁的。
处理完之后执行一次重启让服务重新装载:命令面板里选 "Vue: Restart Vue Server",不用重启整个编辑器。
二、takeover 模式与 TS 语言服务的冲突
第二步是理解 takeover 模式。VS Code 内置了一个 TypeScript 与 JavaScript 语言服务,Volar 自己也带一套。两套服务同时工作时,.vue 文件里的 TypeScript 提示可能来自其中任意一套,而内置那套其实读不懂 Vue 单文件组件的 <script setup> 结构。
takeover 模式的含义是把 TS 语言服务交给 Volar 统一提供。切换方式是在扩展列表里找到 "TypeScript and JavaScript Language Features",选择"禁用(工作区)",只对当前项目生效,不影响其他工程。
启用成功与否可以看一个信号:状态栏右下角的 TypeScript 版本指示会变化,且悬停信息里会带上 Vue 相关的来源。若看不出来,就把光标放到一个 ref 变量上,能正确推断出类型基本就说明接管成功。
这一步的适用边界要留意:如果你的工程完全是 JavaScript、没有任何类型标注,takeover 带来的收益有限,主要作用是避免两套服务互相干扰而不是获得更多提示。

三、配置文件缺失或范围写错
第三步看配置。Volar 依赖 tsconfig.json 或 jsconfig.json 来判断哪些文件属于当前工程,以及用哪套编译选项去推断类型。
一个最小可用的配置长这样:
{
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"exclude": ["node_modules", "dist"]
}
关键是三条:include 必须出现 *.vue 这条,否则 .vue 文件压根不进工程;exclude 不要把源码目录排除掉;如果用了 monorepo,include 里的路径要指向子包而不是仓库根。
纯 JavaScript 工程用 jsconfig.json,内容基本一致:
{
"include": ["src/**/*.js", "src/**/*.vue"],
"compilerOptions": {
"checkJs": false
}
}
还有一个隐蔽的情况:你把 VS Code 打开在了父目录,而这个 Vue 工程只是其中一个子文件夹。此时语言服务在父目录找不到任何配置,就会退化成"按单文件处理",模板里的组件来自哪里它一概不知。修法是直接打开项目根目录,或者在多根工作区里把这个文件夹加进去。
模板里的标签与属性写法记不清时,翻 HTML 参考手册 对一下最快,那里按标签分类列好了。

四、排查顺序与验证清单
把定位固化成一条可复现的流程(预期结果,未在本机执行):
- 检查:打开一个 .vue 文件,看状态栏右侧的语言模式是不是 Vue;不是就手动切换一次;
- 运行:执行
code --list-extensions,列出所有启用扩展并筛 Vue 相关项; - 配置:保留一个语言服务扩展,禁用另一个,并在工作区禁用内置 TS 服务以启用 takeover;
- 安装:项目根缺 tsconfig.json 时补一个,include 里加上
src/**/*.vue; - 预期:在
<script setup>里输入一个已导入组件名的前两个字母,补全列表立刻弹出; - 失败:仍然没有提示,改看是不是打开了父目录,改成打开项目根重试;
- 修复:多根工作区场景下,把子工程逐个添加为工作区文件夹;
- 验证:重启 Vue 语言服务后,在模板里输入
<应弹出已注册组件列表。
排错的价值在于顺序:先排除扩展冲突这种一次性问题,再动配置。反过来做容易在错误的方向上反复试。
总结
Vue 文件的智能提示由语言服务提供,出问题就沿着"谁在提供服务、它能不能读到配置、配置覆盖到哪些文件"这条链往下查。
四条带走:
- Vue 语言服务扩展只保留一个,混用必冲突;
- takeover 模式解决的是两套服务打架,不是提速度;
- tsconfig 或 jsconfig 的 include 必须包含
*.vue; - 用项目根目录打开工作区,别打开父目录。
下一步建议把 .vscode/extensions.json 提交进仓库,写清推荐与不推荐的扩展,团队里就不会有人再同时装两个。
常见问题
Q:为什么 Vue 文件里完全没有任何提示?
A:先确认装了 Vue 语言服务扩展,再看是否用项目根目录打开了工作区。两者都正常时,检查有没有配置文件被错误排除。
Q:Vetur 和 Volar 能一起装吗?
A:不建议。两者都对 Vue 文件提供语言服务,同时启用会互相干扰,表现为补全重复或部分失效。按项目版本留一个。
Q:什么是 takeover 模式?
A:让 Volar 接管 TypeScript 语言服务的模式。启用后 .vue 里的类型推断由同一套服务负责,避免两套服务给出不一致的结果。
Q:加了 tsconfig.json 还是没提示怎么办?
A:重点检查 include 是否包含 src/**/*.vue,以及是否被上层的 exclude 排除。改完记得重启 Vue 语言服务。
Q:为什么换台电脑打开同一个项目就有提示?
A:通常是本地扩展组合不同。用仓库里的推荐扩展清单统一一遍,比逐台排查更省时间。
延伸学习
想把编辑器这块配顺,可以按这个顺序来:
- 想在真实项目里练一遍编辑器与工程的配合,VSCode+AI 开发网页教程 可以跟一遍;
- 读一篇相关笔记 VSCode 中设置 tpl,vue 高亮,看别人怎么处理文件关联;
- 想找可用的前端资源与工具,翻 Javascript 开发资源 最快。

TRAE-AI编程



