
做 Vue 开发的朋友应该都有过这种经历新建一个.vue文件不是跑到旧组件里复制一份就是翻出之前的笔记手动敲一遍 template、script 和 style。组件简单还好说一旦项目进入业务迭代阶段每天要新建十几个组件光是复制粘贴、删多余代码、补缺失片段这些事就够烦人的。今天这篇笔记聊的就是怎么让 VS Code 帮你把这套动作自动化——配置用户代码片段User Snippets输入一个简短前缀自动生成完整 vue 组件模板。我会按实际操作顺序把步骤拆开讲特别是关键界面长什么样、每个配置项是什么意思都尽量写清楚。这套方法不需要安装任何第三方插件属于编辑器自带能力电脑离线也能用。适合刚开始学 Vue 不久、还在手动复制模板的新手也适合项目里写了半年组件、每次建文件都在删删改改的老手。1. 手动创建 Vue 组件太痛苦先说说三个痛点1.1 每天复制粘贴模板还总缺胳膊少腿我最开始接触 Vue 时建组件的流程是找一个结构最像的旧文件复制改名然后疯狂删除不相关的代码。这个过程听起来简单实际非常坑。旧文件里往往带着上一个组件的 props、computed、方法甚至业务逻辑删除时稍微手滑就会留下一个没有使用过的变量或者一段被注释掉的死代码。等代码审查时再发现又得回头清理非常消磨耐心。更麻烦的是一个人的习惯会被复制进下一个文件。今天从列表页复制明天从详情页复制时间一长你项目里的组件会同时存在好几种“风格”的根节点、几种不同的写法。比如有人喜欢在script里写data()有人用script setup有人会忘记给style加scoped。这类问题本身不致命但会让代码库变得很“脏”排查问题时很容易被这些杂音干扰。1.2 团队规范难统一代码风格各写各的只要是几个人一起维护项目就一定会遇到规范问题。我在某个项目里见过一种情况同一个模块里三个同事写了三种不同的组件写法。一个用选项式 API 并习惯把所有逻辑放在methods里一个用了组合式 API 但喜欢把ref集中放在顶部还有一个虽然也用script setup但 import 顺序乱七八糟。代码本身都能跑但互相 review 时总得花额外时间解释“我这个写法是习惯”。统一规范最有效的办法不是贴文档而是让编辑器直接生成“符合规范”的代码。模板里缩进用两空格还是四空格、引号用单引号还是双引号、props 写在哪个位置全都在生成那一刻固定下来。每个人创建的组件从出生起就是一个模子review 时自然少了很多口水仗。1.3 新同事上手慢教程文档没人看项目文档里写清规范当然好但说实话真正会逐字读文档的新人不多。新人上手项目时最需要的是“照着做的事情”比如新建一个组件后看模板就知道 props 在哪里写、方法挂在哪里、样式区域怎么组织。这时候一套设计良好的组件模板比任何教程都管用。我以前带过一个 A 同学他刚进项目时总是问“这个组件的文件结构应该怎么搭”。后来我把团队模板配好他在编辑器里输入前缀直接生成标准结构问题自然就消失了。所以模板这东西表面上是省时间实际上还在帮团队沉淀开发习惯属于一次投入、长期受益的事。2. 选对方案用户代码片段比插件更适合模板生成2.1 对比插件与代码片段为什么我更推荐后者提到“快速生成代码”很多人第一反应是装插件。VS Code 插件市场里确实有提供 Vue 代码片段的扩展用起来也方便。但我实际对比之后还是更倾向于用编辑器自带的用户代码片段功能原因主要有几个。插件方案的核心问题是“不可控”。你装的扩展内置了什么模板、什么触发词、什么语法风格都由插件作者决定。遇到某些插件模板和团队规范不一致时还得去翻插件文档找自定义入口折腾半天可能还是改不了。而用户代码片段是 VS Code 内置功能配置文件就是一个 JSON 文件每一行输出都是你自己的想怎么改就怎么改。表格对比会更直观对比维度用户代码片段第三方扩展安装成本编辑器自带零安装需要联网安装并信任作者定制能力完全可控改 JSON 即可受插件声明的功能限制离线环境完全可用部分扩展离线功能受限团队共享一个 JSON 文件随仓库同步要求每个人都有同一个扩展长期维护自己维护想换随时换依赖作者更新和维护还有一点很关键用户代码片段可以放在项目目录的.vscode文件夹里跟着代码仓库一起提交。团队成员拉取代码之后模板自动生效不需要每个人单独装一遍扩展、单独调一遍配置。这一点对团队协作特别友好后面我会专门讲怎么同步。2.2 一个合格的 Vue 组件模板应该包含哪些内容在配模板之前先想清楚模板里到底要放什么。一个“合格”的 Vue 组件模板至少要覆盖这几个方面完整的template根节点、script setup标签、带scoped的style样式区以及一些高频使用的占位位置比如 props、emits、状态变量、挂载生命钩子和方法。为什么根节点和scoped这么重要因为 Vue 单文件组件要求模板必须有且只有一个根节点而style scoped能避免样式污染其他组件。很多新手手动写组件时最容易漏的就是这两个东西模板里直接写死能省掉不少低级报错。至于script setup这是 Vue 3 推荐的组合式 API 写法。现在新项目基本都用这种方式老项目如果还在用选项式 API也可以准备一套对应模板。关键是要让模板契合项目现状而不是一味追求“最新最全”这一点在实际配置时需要务实地考虑。2.3 先搞懂 snippet 的四个关键概念后面不踩坑如果你没接触过代码片段配之前最好先了解几个基本概念。第一个是prefix也就是触发词。你在编辑器里输入这两个字母VS Code 才会弹出这个模板的提示。第二个是body它决定了模板会展开成什么内容。注意 body 是一个数组数组里的每个元素最终会成为展开文本的一行。第三个是占位符$1、$2这种。模板展开后光标会先停在$1位置按下 Tab 会跳到$2再按 Tab 跳$3这样你就可以按顺序填写每个关键位置。占位符还能写带默认值的形式比如${1:container}展开时这个位置的文本会处于选中状态你直接输入就能整体替换成自己的内容。第四个是内置变量。$TM_FILENAME_BASE代表当前文件去掉扩展名后的文件名比如你新建了一个UserCard.vue文件这个变量就代表UserCard。用它在模板里自动带上组件名能省掉不少手动改名的操作。这四个概念搞懂之后看任何 snippet 配置都不会再是一头雾水。3. 5 分钟搞定配置完整步骤与代码模板3.1 第一步打开代码片段配置文件整个配置过程的第一步是打开用户代码片段管理面板。在 VS Code 里按CtrlShiftP打开命令面板然后在输入框里输入snippets命令列表会实时过滤只剩一项叫“首选项配置用户代码片段”英文环境下是Preferences: Configure User Snippets。回车进去后会弹出一个文件选择列表。这个列表里会列出所有 VS Code 认识的文件类型。你可以从里面选一个叫Vue的选项回车之后编辑器会创建一个vue.json文件这个文件专门存放 Vue 文件的代码片段。如果列表里没有 Vue 这个选项或者你找不到它还有一个更稳妥的办法选择列表最上面的“新建全局代码片段文件...”然后输入vue回车一样会生成一个vue.code-snippets文件效果几乎相同。这一步完成后编辑器右侧会打开一个 JSON 文件里面默认是一个空对象。接下来要做的就是把我们的模板配置写进去。虽然界面看起来有点冷冰冰但它本质上就是一个文本文件所以完全不用有心理负担。3.2 第二步粘贴模板代码逐行看懂配置打开vue.json后把下面的内容复制进去{ Vue3 基础组件模板: { prefix: vuebase, body: [ template, div class\${1:container}\, $2, /div, /template, , script setup, // 如果项目未配置自动导入请在这里手动补充以下 import, // import { ref, onMounted } from vue, defineProps({, // 在这里定义 props, }), , defineEmits([]), , // 状态, const $3 ref(), , // 生命周期, onMounted(() {, // TODO: 在这里写挂载逻辑, }), , // 方法, function $4() {, $5, }, /script, , style scoped, .${1:container} {, /* 在这里写样式 */, }, /style ], description: Vue3 基础组件模板使用 script setup 语法 } }这里面有几个地方值得停下来专门解释。第一条Vue3 基础组件模板是这个片段的名字之后在编辑器提示列表里你看到的就是它。prefix: vuebase是触发词你在.vue文件里输入vue时补全列表会出现vuebase回车或按 Tab 就会展开整个模板。body 里的双引号都写成了\这是因为整个配置文件是 JSON 格式JSON 字符串里的双引号必须转义否则解析器会认为字符串提前结束了。这也是新手最容易写错的地方很多人的 snippet 配置失效都是因为引号转义出了问题。再看$3和$4这种占位符。模板展开后你的光标首先出现在${1:container}这处此时container是选中状态你直接输入userCard之类的类名两处同时变成userCard一处是根节点 class另一处是style里的选择器。按 Tab 跳到$2填模板内容区域再按 Tab 填$3的状态变量名然后是$4的方法名最后到$5方法体内部。整个过程完全不碰鼠标效率非常可观。你看这个模板里没有直接写import { ref, onMounted } from vue而是在注释里提醒手动补充这是刻意为之。因为很多组件只用到ref或只用到生命周期预置 import 会触发 ESLint 的未使用变量警告。如果你的项目里配置了自动导入能力那么模板生成后连这条注释都可以删掉如果没有就照注释提示手动补一行。这个取舍逻辑在实际开发中非常常见——模板要服务绝大多数场景而不是服务想象中“什么都会用到”的理想场景。3.3 第三步在 .vue 文件中触发模板试试效果配置保存后立刻就能验证。新建一个文件比如UserCard.vue确认 VS Code 右下角的文件语言已经识别为 Vue。然后在这个文件里输入vuebase你会看到智能补全列表中出现一个条目右侧显示“Vue3 基础组件模板”。按 Tab 或回车整个模板瞬间展开。这时候屏幕上是你再熟悉不过的组件结构template div classcontainer /div /template script setup // 如果项目未配置自动导入请在这里手动补充以下 import // import { ref, onMounted } from vue defineProps({ // 在这里定义 props }) defineEmits([]) // 状态 const ref() // 生命周期 onMounted(() { // TODO: 在这里写挂载逻辑 }) // 方法 function () { } /script style scoped .container { /* 在这里写样式 */ } /style注意此时classcontainer里的container和style里的.container都是选中状态。输入UserCard后按 Tab两处会同步变成.user-card或你填的任何名字。再按 Tab光标会跳到模板正文区域继续按 Tab 依次填状态变量名、方法名、方法体。第一次看到模板自动展开的效果时建议不要急着删掉而是按几次 Tab 把整个流程走一遍。这个过程能帮你直观理解占位符的跳转顺序。如果某个位置不需要比如组件没有生命周期逻辑直接把onMounted那段删掉就行模板只是给你一个起点不是死板的最终结果。3.4 第四步把常用变体模板也一起配好一个基础模板肯定不够用。实际开发中TypeScript 项目、页面路由组件、列表项这种高频场景都应该有自己的模板。我建议按项目类型准备 2 到 3 套模板即可太多反而记不住触发词。TypeScript 项目的组件模板可以这样写触发词用vuets{ Vue3 TS 组件模板: { prefix: vuets, body: [ template, div class\${1:container}\, $2, /div, /template, , script setup lang\ts\, import { ref, computed } from vue, , interface Props {, // 在这里定义 props 类型, title?: string, }, , withDefaults(definePropsProps(), {, title: , }), , const $3 ref(), , const $4 computed(() $3.value), , defineExpose({, // 在这里暴露给父组件的方法或属性, }), /script, , style scoped, .${1:container} {, /* 在这里写样式 */, }, /style ], description: Vue3 TypeScript 组件模板 } }这段模板用了langts并默认带上了interface Props和withDefaults。withDefaults是 Vue 3.3 之后推荐的写法类型安全做得更好如果你的项目版本还在 3.2 及以下可以用definePropsProps()加withDefaults的组合或者直接省略默认值部分。页面路由组件模板则适合业务页面场景触发词用vupage{ Vue3 页面组件模板: { prefix: vupage, body: [ template, div class\page-container\, h1{{ route.meta.title || 页面标题 }}/h1, $1, /div, /template, , script setup, import { useRoute, useRouter } from vue-router, import { ref, onMounted } from vue, , const route useRoute(), const router useRouter(), , const $2 ref([]), , function $3() {, // TODO: 在这里获取数据, }, , onMounted(() {, $3(), }), /script, , style scoped, .page-container {, padding: 16px;, }, /style ], description: Vue3 路由页面组件模板适合业务页面 } }页面模板和组件模板的差异在于内置了路由相关逻辑。你按 Tab 到$3时把函数名改成fetchData模板里function $3()和onMounted里调用处的$3()会同步更新不需要改两遍。这种“同一个占位符出现在多处、只需要填一次”的特性正是 snippet 配置中最实用的能力之一。如果项目还要拆出列表项模板、表单弹窗模板思路完全一样把高频的代码骨架放进 body 即可。模板数量控制在 5 个以内比较合理多了反而记不住触发词。我一般还会给每个模板的 description 写清楚用途方便补全列表里快速区分。4. 进阶玩法让模板贴合项目而不是只做一个花瓶4.1 用 Tab 键把光标停在最该填的位置模板展开只是第一步真正决定效率的是 Tab 跳转顺序的设计。设计模板时你要想清楚一个组件创建出来后用户最先改的是什么对于大多数组件来说最先改的是根节点类名然后是模板内容再是状态变量名、方法名。所以我的设计里$1永远是类名$2是模板内容区$3和$4依次往后排。这样一来展开后你只需要按顺序“填空”整个流程像走流程单一样清晰。如果你把$1放在不重要的注释位置光标就得跳好几下才能到核心区域体验会差很多。还有一个细节值得说让同一个占位符出现在多个位置。比如${1:container}同时出现在模板根节点和style选择器里你只需要输入一次两处同时生效。这个方法在写组件时特别有用因为根节点类名和样式选择器本来就应该保持一致手写两遍反而容易打错。4.2 让模板自动带上当前组件名告别手改每次新建组件都要手动填类名和组件名虽然已经比复制粘贴强多了但还可以更懒。VS Code 代码片段支持内置变量其中$TM_FILENAME_BASE能读取当前文件名。你可以把模板里的类名占位改成${1:$TM_FILENAME_BASE}这样新建UserCard.vue文件后输入触发词模板展开时类名自动就是UserCard。不过实际用的时候要注意一个细节类名推荐用小写连字符风格比如user-card但文件名用的是大驼峰UserCard.vue直接套用$TM_FILENAME_BASE会得到UserCard而不是user-card。所以更稳的做法是保留$1占位符让用户手动输入类名或者接受UserCard作为类名并在模板注释中说明项目可以使用大驼峰类名。不同项目的 CSS 命名规范不同这里需要你自己权衡。如果你特别想用文件名自动生成也可以配合 VS Code 的一个内置功能模板展开后用CtrlSpace触发补全输入user-card时 VS Code 会基于当前文件名给出转换建议不过这个行为受扩展影响较大不建议作为主要依赖。我在项目中最终还是选择了“占位符 手动输入”的方式因为类名规范这种东西每个团队都不一样写死在模板里反而束缚手脚。4.3 配合自动导入和 ESLint模板也能很智能之前提到基础模板里没有预置 import这是为了避开 ESLint 的未使用变量警告。但如果你项目里配置了自动导入能力比如 VS Code 里装了 Auto Import 之类的扩展或者项目本身使用自动导入插件那模板里就可以放心写ref、computed、onMounted因为保存时这些导入会被自动补充。如果项目没有自动导入能力我的建议是模板中的import全部采用“注释提示”而不是“实际写入”。模板展开后需要哪个导入就取消哪行注释或者直接输入ref然后手动补一行import { ref } from vue。这样避免了生成一个有一堆红色波浪线警告的“脏”组件。ESLint 配置比较严格的团队还会关注模板本身的缩进、引号、换行。配置 snippet 时请确保 body 里每一行的缩进、引号风格和项目.eslintrc配置一致。比如项目规定单引号body 里就不要出现双引号字符串项目规定两空格缩进body 里就统一用两个空格不要用 Tab 字符。4.4 把模板同步给团队成员统一开发基线模板配置好之后如果只存在本地全局配置文件里换台电脑就丢了团队成员也用不上。正确的做法是把它放进项目目录的.vscode文件夹并且命名成vue.code-snippets。VS Code 会自动识别项目目录下.vscode文件夹里的所有*.code-snippets文件不需要额外配置。具体做法很简单在项目根目录新建.vscode文件夹在里面新建vue.code-snippets文件把之前写好的 JSON 内容全部复制进去。然后在 git 里正常提交这个文件。团队其他人拉取代码时VS Code 会自动为这台机器上的项目启用这套模板不需要任何额外操作。这一点我实测下来很稳基本不存在版本冲突的问题。唯一需要注意的是确认.gitignore里没有忽略.vscode目录。有些项目为了让每个人个性化设置会把.vscode整个忽略掉这样的话模板文件就同步不了。解决办法是把vue.code-snippets单独加入白名单或者干脆全局用一份配置但团队成员各自维护稍显麻烦。就我目前的经验来说项目级配置始终是团队场景下的最优解全局配置只适合个人电脑使用。5. 常见问题与排查模板不生效的几种原因5.1 输入前缀完全没反应怎么办这是最常见的翻车现场。如果你输入vuebase后什么提示都没有先别急着怀疑配置写错按顺序排查。第一步看当前文件类型VS Code 右下角状态栏会显示当前语言模式必须显示为 Vue 才行。如果显示的是纯文本或 JavaScript代码片段不会生效这时点击语言模式手动选择 Vue。第二步确认配置文件写对了位置。如果你在命令面板里选择的是“全局用户代码片段”它会存放在当前用户目录下的配置文件夹里对所有项目生效。如果你建的是项目级片段它只对该项目生效打开其他项目当然找不到。第三步检查 JSON 是否解析失败。代码片段文件如果有语法错误VS Code 会在打开文件时标红左下角也可能弹出错误提示此时配置完全不会生效把错误处改掉即可。触发词本身也可能有问题。prefix的值不要和其他片段冲突比如你配的vue可能和某个插件自带的触发词冲突导致你自己的不显示。更保险的做法是使用不太常见的词比如vuebase、vuets、vupage这样可以大幅降低冲突概率。5.2 展开后的模板格式不对保存后变乱有朋友会碰到一种情况模板展开时缩进正常但保存文件后格式大变import 顺序被重排自动补了缺失的引号整个代码布局被格式化工具接管了。这个现象通常不是 snippet 的错而是 VS Code 的“保存时格式化”功能在起作用。解决思路有两种。第一种是让模板本身就符合格式化工具的规则。比如 Prettier 默认强制单引号、两空格缩进模板 body 就必须严格遵守这个风格。第二种是调整模板的书写方式body 数组里不要写多余的空行不要在行尾留空格否则格式化工具会把它们清掉导致你原本的排版被“修正”。还遇到过一种情况是模板展开后所有字符都挤在一行没有换行。这几乎可以肯定是 body 数组写错了比如把整个模板内容写成了一个字符串而没有按行拆分成数组元素。记住body 里每一行都是一个数组元素元素之间用逗号分隔空行也要用一个空字符串来表示。5.3 占位符没有按预期跳转或替换Tab 跳转不按顺序来通常是因为模板里的占位符编号重复或者漏编。$1、$2、$3应该按你希望的光标移动顺序从小到大编写。如果跳转顺序乱了检查一下是不是把$1写在了不该出现的位置或者有两个$1同时存在。还有一个小坑是${1:container}这种带默认值的写法。如果你希望同一处占位符在多个位置都生效那么所有位置的占位符写法必须完全一致。比如一处写${1:container}另一处写${1:userCard}这是两个不同的占位符不会联动替换。这属于新手容易踩的细节坑但排查起来并不难对比两处写法是否一字不差即可。5.4 团队同步时文件不生效或编码问题项目级.vscode/vue.code-snippets文件拉下来后没有生效先检查文件编码。如果原来的配置里包含中文字符文件保存为 UTF-8 是必须的否则 VS Code 可能读出一堆乱码并报 JSON 解析失败。窗口右下角状态栏能查看当前文件编码确认是 UTF-8 后重新保存一次。另外VS Code 对代码片段的文件名后缀有约定项目级片段必须以.code-snippets结尾。如果你命名成了vue.json放在.vscode下VS Code 不会自动识别。全局配置时用vue.json没问题因为那是编辑器默认约定的文件名但项目级配置必须遵循.code-snippets后缀规则这个区别容易忽略。团队场景下还有一个隐含要求配置文件中的说明文字description尽量写成中文或英文都好但引号、逗号必须是半角字符。如果你从 Word 或某些笔记软件里复制的文本带了全角符号JSON 会直接报错排查起来非常隐蔽遇到这类问题不妨把所有引号手动重敲一遍。5.5 模板生成了但有红色波浪线警告模板展开后出现ref is not defined或者onMounted is not defined之类的警告原因就是我们前面提到的“模板里没有预置 import”。这属于刻意设计不是配置错误。处理方式有两种项目配置了自动导入就直接忽略保存时插件会自动补没有自动导入就在模板最上面补一行import { ref, onMounted } from vue。还有一种情况是模板里定义了defineProps但整个组件没用到 propsESLint 可能提示定义未使用这在 script setup 里其实不会算未使用变量因为 defineProps 是编译器宏。如果你项目里的 ESLint 规则特别严格把不用的defineProps、defineEmits整段删掉就行模板本身只是一个起点不应该成为约束你删改代码的负担。我把这套模板在某公司项目里用了快一年过程中最深的体会是模板不是一个“配完就完事”的东西它应该跟着项目一起演进。项目从 JS 切到 TS那就增加vuets模板页面风格统一了那就把页面模板里的默认类名和 padding 值调成一致。每隔几周回头看一遍模板删掉那些从来用不到的占位符加上新出现的常用代码它才会一直保持“顺手”的状态。建议你今天就打开 VS Code花十分钟配一套基础模板然后连续用一周再根据自己的习惯做调整之后你就会发现——原来新建组件这件事也可以这么不费脑子。