﻿---
title: 用 Code Snippets 少敲点字
date: 2026-02-05
tags:
  - VSCode
  - Neovim
  - Workflow
  - Markdown
excerpt: "开发者经常面对重复的编码模式，从标准的 if/for 结构到 Go 的错误处理或 HTML 模板。这种重复既低效又容易出错。代码片段（Snippets）是最佳解决方案：输入一个短前缀（如 if、for），IDE 就会建议一个补全项，展开后即为预定义的代码模板。"
lang: zh-CN
i18n:
  en: /en/vscode_snippets
  translation: 2
updated: 2026-05-23 00:30:59
---

<script data-swup-reload-script type="module" src="/js/components/tab.js"></script>

## 创建你的第一个 Snippet

> 代码片段是简化输入重复代码模式的模板，例如循环或条件语句。

创建 Snippet 的步骤：

1. 按 <kbd>Ctrl + Shift + P</kbd> 打开命令面板，搜索"Configure User Snippets"。
2. 选择 Snippet 的作用范围：
   - **全局：** 在所有文件类型中可用。
   - **语言特定：** 仅限于特定语言（如仅 JavaScript）。

在 VS Code 中选择 Snippet 作用范围后，编辑器会自动创建或打开对应的 JSON 文件：文件名以关联语言命名（如 Markdown 对应 `markdown.json`），全局 Snippet 则存储在专用的 `global.json` 文件中。

一个 Snippet 文件可以定义多个片段。每条记录遵循以下结构：

| 属性                    | 说明                                           |
| :---------------------- | :--------------------------------------------- |
| `{json} "prefix"`       | **触发词：** 用于激活片段的关键字。             |
| `{json} "body"`         | **内容：** 代码数组（支持多行）。               |
| `{json} "description"` | **提示：** 在补全菜单中显示的可选说明。         |

先看 2 个场景：

<script data-swup-reload-script type="module" src="/js/components/accordion.js"></script>

<x-accordion>
  <accordion-item title="场景 1：嵌入 WebM 视频">

  有时我会在 Markdown 文章中插入 WebM 格式的动图。标准 HTML 结构有点啰嗦：

  ```html
  <video autoplay loop muted playsinline>
    <source src="https://assets.vluv.space/job_control.webm" type="video/webm">
  </video>
  ```

  </accordion-item>
  <accordion-item title="场景 2：自定义手风琴组件">

  我的项目中有一个自定义的手风琴（Accordion）组件。它接受两个占位符：`$1` 用于标题，`$2` 用于内容。

  ```html
  <x-accordion>
    <accordion-item title="What'you Name?">
      My name is GnixAij.
    </accordion-item>
  </x-accordion>
  ```

  </accordion-item>
</x-accordion>

所以我在 `markdown.json` 中写了一些 Snippet，这样就可以通过输入前缀并接受补全结果来轻松插入 HTML 模板。

<x-tabs>

<x-tab title="预览" active>

<video autoplay loop muted playsinline>
  <source src="https://assets.vluv.space/snippet_demo.webm" type="video/webm">
</video>

</x-tab>

<x-tab title="Snippet">

```json markdown.json
{
	"animated_image": {
		"prefix": "video",
		"body": [
			"<video autoplay loop muted playsinline>",
			"  <source src=\"$1\" type=\"video/webm\">",
			"</video>"
		]
	},
	"Accordion": {
		"prefix": ["x-accordion", "accordion"],
		"body": [
			"<x-accordion>",
			"  <accordion-item title=\"$1\">",
			"    $2",
			"  </accordion-item>",
			"</x-accordion>"
		],
		"description": "Accordion custom element with expandable items"
	}
}
```

</x-tab>

</x-tabs>

## 一次定义，多编辑器通用

如今，VS Code 的各种分支层出不穷，包括 Cursor、Windsurf 和 Trae，这让在不同编辑器之间维护代码片段变得相当麻烦。不同编辑器将 Snippet 存储在各自的默认目录中，如下所示：

| 编辑器                   | Snippet 目录                          |
| ------------------------ | ------------------------------------ |
| VSCode/Cursor/Trae       | `<UserDataFolder>/User/snippets`[^1] |
| NeoVim 使用 `blink.cmp` | `~/.config/nvim/snippet` [^2]        |

以下是我在统一维护 Snippet 的方法（完整方案可参考我的 [[dotbot|文章]]）：将所有 Snippet 文件集中存储在 `<dotfiles_folder>/path/to/snippets` 目录中，然后为每个编辑器创建指向该目录的**符号链接**：

```nu
$ ls ~/.config/nvim `~/Library/Application Support/Code/User/` --long | where type == symlink | select name target

╭───┬───────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────╮
│ # │                               name                                │                              target                              │
├───┼───────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ 0 │ /Users/gjx/.config/nvim/snippets                                  │ /Users/gjx/Projects/dotfiles/application/vscode/snippets         │
│ 1 │ /Users/gjx/Library/Application Support/Code/User/keybindings.json │ /Users/gjx/Projects/dotfiles/application/vscode/keybindings.json │
│ 2 │ /Users/gjx/Library/Application Support/Code/User/settings.json    │ /Users/gjx/Projects/dotfiles/application/vscode/settings.json    │
│ 3 │ /Users/gjx/Library/Application Support/Code/User/snippets         │ /Users/gjx/Projects/dotfiles/application/vscode/snippets         │
╰───┴───────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────╯
```

这样一来，我只需维护一份 Snippet 副本，所有编辑器共用，无需重复工作。

## 延伸阅读

- 更详细的语法说明，请参考[官方文档](https://code.visualstudio.com/docs/editing/userdefinedsnippets#_snippet-syntax)。
- 我的 Snippet 集合，请参考 [Efterklang/dotfiles](https://github.com/Efterklang/dotfiles/tree/main/application/vscode/snippets)。

[^1]: 用户数据文件夹的位置因平台而异：Windows 为 `%APPDATA%/Code`，Linux 为 `~/.config/Code`，macOS 为 `~/Library/Application Support/Code`
[^2]: Blink 默认使用 `vim.snippet` API 来展开和导航代码片段。内置的 `snippets` 源会加载 [friendly-snippets](https://github.com/rafamadriz/friendly-snippets)（如果可用），并加载 `~/.config/nvim/snippets/` 中找到的所有片段。[Snippets | Blink Completion (blink.cmp)](https://cmp.saghen.dev/configuration/snippets)
