代码片段是帮助快速输入重复代码模式的模板,例如循环和条件语句。
在 Visual Studio Code 中,代码片段会与其他建议一起显示在 IntelliSense 中,可按 Control+Space 调出;也可以在命令面板运行“插入代码片段”(Insert Snippet),打开专门的选择器。
还可以启用 Tab 补全:设置 "editor.tabCompletion": "on",输入片段前缀,也就是触发文本,再按 Tab 插入。
片段语法遵循 TextMate 片段语法,但不支持“插值 shell 代码”和 \u。
内置代码片段
VS Code 为 JavaScript、TypeScript、Markdown、PHP 等多种语言提供内置片段。

在命令面板运行 Insert Snippet,可以查看当前文件语言可用的片段。该列表不仅包括内置片段,也包括用户自行定义的片段,以及已安装扩展提供的片段。
从 Marketplace 安装片段
Visual Studio Marketplace 中很多扩展包含代码片段。打开扩展视图,macOS 快捷键为 Shift+Command+X,Windows、Linux 为 Ctrl+Shift+X,再使用过滤条件 @category:"snippets" 搜索。

找到需要的扩展后安装,再按原文说明重启 VS Code,即可使用新片段。
创建自己的代码片段
无需扩展就能自行定义片段。在“文件 → 首选项”中选择“配置代码片段”(Configure Snippets),然后按语言标识符选择适用语言;如果希望对所有语言可用,选择“新建全局代码片段文件”(New Global Snippets file)。VS Code 会负责创建和刷新底层片段文件。

片段文件使用 JSON,支持 C 风格注释,并可定义任意数量的片段。片段支持大多数 TextMate 动态语法,会根据插入上下文智能调整空白,还支持方便的多行编辑。
以下是 JavaScript 的 for 循环片段:
// in file 'Code/User/snippets/javascript.json'
{
"For Loop": {
"prefix": ["for", "for-const"],
"body": ["for (const ${2:element} of ${1:array}) {", "\t$0", "}"],
"description": "A for loop."
}
}
其中:
"For Loop"是片段名称;没有提供 description 时,IntelliSense 显示该名称。prefix定义一个或多个触发词,用于在 IntelliSense 中显示片段。前缀采用子字符串匹配,因此示例中的fc可以匹配for-const。body是一行或多行内容,插入时会连接成多行。换行与内嵌 Tab 会根据插入上下文调整格式。description是可选说明,在 IntelliSense 中显示。
示例 body 还包含三个占位符,按跳转顺序分别是 ${1:array}、${2:element} 和 $0。按 Tab 可快速跳到下一个占位符,随后编辑它或继续跳过。
冒号后的字符串是默认文本,例如 ${2:element} 中的 element。占位符按编号从一开始递增遍历;零是可选的特殊编号,始终最后访问,并在指定位置结束片段模式。
文件模板片段
如果片段用于填充或替换整个文件,可在定义中加入 isFileTemplate。在新文件或现有文件中运行“Snippets: Fill File with Snippet”,这些文件模板片段会显示在下拉列表中。
片段作用域
作用域确保只建议相关片段。可以按适用语言划分,也可以按适用项目划分;范围可以是一个、多个或全部。
语言作用域
片段定义在特定语言文件或全局文件中,由此决定它适用于一种、多种还是所有语言。
单语言用户片段放在对应语言的文件里,例如 javascript.json。通过“Snippets: Configure Snippets”按语言标识符打开。只有编辑该语言文件时,片段才可用。
多语言和全局片段放在扩展名为 .code-snippets 的 JSON 文件中,也通过相同命令管理。全局片段定义可以额外包含 scope,指定一个或多个语言标识符。如果没有 scope,该片段对全部语言可用。
大多数用户自定义片段只面向一种语言,因此通常放在对应语言文件中。
项目作用域
也可以把全局片段文件限制在某个项目中。在配置片段的下拉列表选择“New Snippets file for ‘<folder-name>’…”,即可在项目根目录的 .vscode 文件夹中创建项目片段。
项目片段便于与参与同一项目的其他人共享。它们与全局片段类似,也能通过 scope 限定语言。
文件模式作用域
使用可选的 include 与 exclude 可以进一步规定片段在哪些文件出现。这两个属性既适用于语言专用文件,也适用于全局文件,还能与 scope 组合:
include:一个 glob 模式或模式数组,指定应该显示片段的文件。exclude:一个 glob 模式或模式数组,指定不应显示片段的文件。
匹配规则如下:
- 仅文件名模式,例如
*.test.ts,只匹配文件名,不受文件在项目中位置的影响。 - 基于路径的模式,例如
**/*.test.ts或**/dist/**,匹配完整文件路径。 - 同时匹配 include 与 exclude 时,exclude 优先。
- 两者都未指定时,片段会出现在 scope 允许的全部文件中。
示例:测试片段
以下片段只在 TypeScript 测试文件中出现:
{
"Test Block": {
"prefix": "test",
"body": ["test('${1:description}', () => {", "\t${0}", "});"],
"description": "Insert a test block",
"scope": "typescript",
"include": ["**/*.test.ts", "**/*.spec.ts"]
}
}
示例:排除目录
以下片段在 JavaScript 文件中出现,但排除 dist 与 node_modules:
{
"Console Log": {
"prefix": "log",
"body": "console.log(${0});",
"description": "Insert console.log",
"scope": "javascript",
"exclude": ["**/dist/**", "**/node_modules/**"]
}
}
示例:配置文件片段
以下使用仅文件名模式,只在 travis.yml 中出现:
{
"Travis CI Node": {
"prefix": "travis-node",
"body": ["language: node_js", "node_js:", " - ${1:18}"],
"description": "Travis CI Node.js configuration",
"scope": "yaml",
"include": ["travis.yml"]
}
}
借助 include 和 exclude,可以让 IntelliSense 只在相关位置显示片段,减少无关建议。
代码片段语法
片段 body 可以使用特殊结构,控制光标和插入文本。
Tab 停靠点
使用 $1、$2 等定义光标位置。数字决定访问顺序,$0 表示最终位置。同一编号的多个停靠点会相互关联、同步更新。
占位符
占位符是带默认值的停靠点,例如 ${1:foo}。默认文本插入后会被选中,便于修改。占位符也可以嵌套,例如 ${1:another ${2:placeholder}}。
选择项
占位符可提供多个候选值,语法为用竖线包围、逗号分隔的列表,例如 ${1|one,two,three|}。片段插入并选中该位置后,会提示选择一个值。
变量
通过 $name 或 ${name:default} 插入变量值。变量未设置时,插入默认值或空字符串。如果变量名未知,也就是没有定义,则插入变量名称本身,并把它变成占位符。
可用的文本、路径、工作区及光标变量:
TM_SELECTED_TEXT:当前选中的文本,或空字符串。TM_CURRENT_LINE:当前行内容。TM_CURRENT_WORD:光标下的单词,或空字符串。TM_LINE_INDEX:从零开始的行号。TM_LINE_NUMBER:从一开始的行号。TM_FILENAME:当前文档文件名。TM_FILENAME_BASE:不含扩展名的文件名。TM_DIRECTORY:当前文档所在目录。TM_FILEPATH:当前文档完整路径。RELATIVE_FILEPATH:相对于已打开工作区或文件夹的路径。CLIPBOARD:剪贴板内容。WORKSPACE_NAME:已打开工作区或文件夹的名称。WORKSPACE_FOLDER:已打开工作区或文件夹的路径。CURSOR_INDEX:从零开始的光标编号。CURSOR_NUMBER:从一开始的光标编号。
当前日期与时间变量:
CURRENT_YEAR:当前年份。CURRENT_YEAR_SHORT:年份后两位。CURRENT_MONTH:两位月份,例如02。CURRENT_MONTH_NAME:月份全名,例如July。CURRENT_MONTH_NAME_SHORT:月份缩写,例如Jul。CURRENT_DATE:两位日期,例如08。CURRENT_DAY_NAME:星期全名,例如Monday。CURRENT_DAY_NAME_SHORT:星期缩写,例如Mon。CURRENT_HOUR:24 小时制小时数。CURRENT_MINUTE:两位分钟数。CURRENT_SECOND:两位秒数。CURRENT_MILLISECOND:三位毫秒数,例如078。CURRENT_SECONDS_UNIX:自 Unix 纪元起的秒数。CURRENT_MILLISECONDS_UNIX:自 Unix 纪元起的毫秒数。CURRENT_TIMEZONE_OFFSET:当前 UTC 时区偏移,形式为+HH:MM或-HH:MM,例如-07:00。CURRENT_TIMEZONE_NAME:当前时区的 IANA 名称,例如America/Los_Angeles。
随机值变量:
RANDOM:六位随机十进制数字。RANDOM_HEX:六位随机十六进制数字。UUID:一个版本 4 UUID。
根据当前语言插入行注释或块注释:
BLOCK_COMMENT_START:块注释起始符,例如 PHP 的/*、HTML 的<!--。BLOCK_COMMENT_END:块注释结束符,例如 PHP 的*/、HTML 的-->。LINE_COMMENT:行注释起始符,例如 PHP 的//。
以下片段在 JavaScript 中插入 /* Hello World */,在 HTML 中插入 <!-- Hello World -->:
{
"hello": {
"scope": "javascript,html",
"prefix": "hello",
"body": "$BLOCK_COMMENT_START Hello World $BLOCK_COMMENT_END"
}
}
变量转换
转换功能可在插入变量前修改其值,由三部分组成:
- 正则表达式,与变量值匹配;变量无法解析时匹配空字符串。
- 格式字符串,可引用正则捕获组,也支持条件插入和简单变换。
- 传递给正则表达式的选项。
下面的示例插入不含扩展名的当前文件名,例如把 foo.txt 转为 foo:
${TM_FILENAME/(.*)\\..+$/$1/}
| | | |
| | | |-> no options
| | |
| | |-> references the contents of the first
| | capture group
| |
| |-> regex to capture everything before
| the final `.suffix`
|
|-> resolves to the filename
其中 TM_FILENAME 解析为文件名;正则捕获最后一个扩展名之前的部分;$1 引用第一个捕获组;最后没有指定正则选项。
占位符转换
占位符转换与变量转换类似,在跳到下一个停靠点时改变占位符文本。输入文本与正则匹配后,根据选项替换一个或多个匹配项,替换内容由格式字符串决定。
同一个占位符的每次出现,都可以基于第一个占位符的值独立定义转换。转换格式与变量转换相同。
转换示例
下列示例像片段 body 中一样放在双引号内,以说明某些字符需要双重转义。输入文件名为 example-123.456-TEST.js。
| 示例 | 输出 | 说明 |
|---|---|---|
"${TM_FILENAME/[\\.]/_/}" | example-123_456-TEST.js | 将第一个点替换为下划线。 |
"${TM_FILENAME/[\\.-]/_/g}" | example_123_456_TEST_js | 将所有点或连字符替换为下划线。 |
"${TM_FILENAME/(.*)/${1:/upcase}/}" | EXAMPLE-123.456-TEST.JS | 全部转为大写。 |
"${TM_FILENAME/[^0-9a-z]//gi}" | example123456TESTjs | 删除所有非字母数字字符。 |
语法定义
下面是片段语法的 EBNF,也就是扩展巴科斯范式。使用反斜杠 \ 可转义 $、} 与反斜杠本身。在 choice 选择项中,还可转义逗号与竖线。
只能转义语法要求转义的字符,不应在这些结构中随意给 $ 添加转义;在 choice 结构内部,$ 和 } 都不应转义。
any ::= tabstop | placeholder | choice | variable | text
tabstop ::= '$' int
| '${' int '}'
| '${' int transform '}'
placeholder ::= '${' int ':' any '}'
choice ::= '${' int '|' text (',' text)* '|}'
variable ::= '$' var | '${' var '}'
| '${' var ':' any '}'
| '${' var transform '}'
transform ::= '/' regex '/' (format | text)+ '/' options
format ::= '$' int | '${' int '}'
| '${' int ':' '/upcase' | '/downcase' | '/capitalize' | '/camelcase' | '/pascalcase' | '/snakecase' | '/kebabcase' '}'
| '${' int ':+' if '}'
| '${' int ':?' if ':' else '}'
| '${' int ':-' else '}' | '${' int ':' else '}'
regex ::= JavaScript Regular Expression value (ctor-string)
options ::= JavaScript Regular Expression option (ctor-options)
var ::= [_a-zA-Z] [_a-zA-Z0-9]*
int ::= [0-9]+
text ::= .*
if ::= text
else ::= text
使用 TextMate 片段
VS Code 也支持已有 TextMate 片段文件 .tmSnippets。详情见扩展 API 文档中的使用 TextMate 片段。
给片段分配键盘快捷键
可以创建自定义快捷键,直接插入某个片段。运行“Preferences: Open Keyboard Shortcuts File”,打开定义快捷键的 keybindings.json,并将 snippet 作为额外参数:
{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log($1)$0"
}
}
该快捷键会调用 Insert Snippet,但不再提示选择,而是直接插入给定片段。快捷键定义方式与平常一样:指定按键、命令 ID,以及可选的 when 条件,控制何时启用。
还可以不在 snippet 参数中内联定义内容,而是通过 langId 和 name 引用已有片段。langId 选择语言,name 指定片段。例如,下面选择适用于 C# 文件的 myFavSnippet:
{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"langId": "csharp",
"name": "myFavSnippet"
}
}
下一步
常见问题
如何使用 .tmSnippet 文件中的现有 TextMate 片段
可以把 TextMate 片段文件打包为 VS Code 可用的扩展。参阅使用 TextMate 片段。
如何让片段插入一个带美元符号的脚本变量
需要转义变量名 $variable 中的 $,避免它在片段展开阶段被解析:
"VariableSnippet":{
"prefix": "_Var",
"body": "\\$MyVar = 2",
"description": "A basic snippet that places a variable into script with the $ prefix"
}
插入结果为:
$MyVar = 2
能否从 IntelliSense 隐藏片段
可以。在 Insert Snippet 下拉列表中,点击片段条目右侧的“Hide from IntelliSense”按钮:

隐藏后,该片段不再出现在 IntelliSense 补全列表中,但仍可通过 Insert Snippet 命令选择。
原文页面标注日期:2026 年 9 月 30 日。
原文:Snippets in Visual Studio Code。本文为该文档的中文译文,示例代码保留原文。











暂无评论内容