vscode添加自定义代码片段snippet

8,325 阅读7分钟

0、 使用方式

ctrl + shift + p --> 首选项:配置用户代码片段(Preferences: Configure User Snippets) --> 新代码片段。

1、 snippet简介

snippet即代码段,代码段是模板,可让你更轻松地输入重复的代码模式,例如循环或条件语句。 我最开始想弄代码片段的动机是因为,每次我想通过console.log打印东西, 变量少还好, 变量一多就分不清哪是哪了。 所以想实现一种方法能在直接在打印变量的同时,也能在控制台上看到变量的名称。所以就学习了下snippet的知识。 以下是我通过对比网上的资料和个人实践总结出来的代码片段相关的知识点。希望可以让大家也能提高下编码的效率。

2、 vscode打开snippet的方式

  1. 文件 --> 首选项 --> 用户代码片段(Config User Snippets) --> 新代码片段
  2. ctrl + shift + p --> 首选项:配置用户代码片段(Preferences: Configure User Snippets) --> 新代码片段。
    然后给自己将要配置的代码片段文件起一个文件名, 出现以下界面就是将要配置的代码文件了。(你可以选择新建代码片段: New Snippets 或者在原有代码片段基础上修改: Existing Snippets)

3、 基础语法

  1. scope: 代码片段作用于哪种语言。 不同语言之间以,隔开。 常用的有javascript, typescript,html,css,vue, vue-html, json, markdown等。 如果设置为""就代表所有地方都生效。 更多
  2. prefix:前缀,代码片段名称, 即输入此名字就可以调用定义的代码片段
  3. body:一个数组, 主体,即模板的主体内容,需要编写的代码写在这里。每一行一个字符串
  4. description:代码片段描述,输入名字后编辑器显示的提示信息。未定义的情况下直接显示对象名。把上面的设置更改为自己想要的样子
  5. $1: 生成代码后光标的初始位置,允许重复。按tab键可以在按照定义的顺序切换。还可以定义$2, $3, ..., $n。 注意: $0 是结束位置。
  6. ${1: placeholders}: 生成代码后光标的初始位置(其中1表示光标开始的序号,字符表示生成代码后光标会直接选中字符
  7. \t: 制表符。 如果想让代码缩进, 前边加个\t。 同理\n是换行
  8. ${1|one,two,three|}: 占位符(Placeholders)可以有多选值,每个选项的值用 , 分隔,选项的开始和结束用管道符号(|)将选项包含。当插入代码片段,选择制制表位(Tabstops)的时候,会列出选项供用户选择
  9. 一些较常用变量, 使用语法: ${TM_SELECTED_TEXT}
TM_SELECTED_TEXT 当前选定的文本或空字符串
TM_CURRENT_LINE 当前行的内容
TM_CURRENT_WORD 光标下的单词的内容或空字符串
TM_LINE_INDEX 基于零索引的行号
TM_LINE_NUMBER 基于一索引的行号
TM_FILENAME 当前文档的文件名
TM_FILENAME_BASE 当前文档的文件名(不含后缀名)
TM_DIRECTORY 当前文档的目录
RELATIVE_FILEPATH 当前文件的相对目录
TM_FILEPATH 当前文档的完整文件路径
CLIPBOARD 剪切板里的内容

CURRENT_YEAR 当前年(四位数)
CURRENT_MONTH 当前月
CURRENT_DATE 当前日
CURRENT_DAY_NAME_SHORT 当天的短名称(’Mon’)
CURRENT_HOUR 当前小时
CURRENT_MINUTE 当前分钟
CURRENT_SECOND 当前秒



插入随机值
RANDOM 6位随机10进制数
RANDOM_HEX 616进制数
UUID 一个版本4的UUID

/** 
286055
f570d8
0a831688-a7f1-4668-9964-f6100114792c
*/

BLOCK_COMMENT_START 块注释开始标识,如 PHP /* 或 HTML <!--
BLOCK_COMMENT_END 块注释结束标识,如 PHP */ 或 HTML -->
LINE_COMMENT 行注释,如: PHP // 或 HTML <!-- -->

4. vscode中使用快捷键插入代码片段

你能够创建代码片段通过使用快捷键的方式。 方法是 cmd+shift+p搜索 keybindings.json。 然后在这个json文件中,首选项: 打开键盘快捷方式 加入你想要通过快捷键加入的 snippet。 下面是我常用的快捷键例子。

重点推荐:

    1. 在终端和文件中切换。 我比较喜欢在控制台中通过node js路径的方式, 查看js的效果。 所以就设置了 ctrl+` 的快捷键方式, 可以在文件和控制台中来回切换。 非常方便
    1. 打印变量。 打印变量是日常开发中最高频的一个操作了。 有了快捷键插入代码片段就方便了。 直接选中变量, 快捷键一按就把选中的变量包裹在console.log()中了。 同样的操作也可以用在html包裹div等操作中, 可以极大的提升工作效率
    1. 文件操作: 将当前文件所在位置显示在左边, 在访达中打开当前文件对应目录, 拷贝当前文件的绝对路径
// 将键绑定放在此文件中以覆盖默认值auto[]
[
  {
    "key": "tab",
    "command": "-acceptSelectedSuggestion",
    "when": "suggestWidgetVisible && textInputFocus"
  },
  {
    "key": "shift+alt+cmd+n",
    "command": "workbench.action.newWindow"
  },
  {
    "key": "shift+cmd+n",
    "command": "-workbench.action.newWindow"
  },
  {
    "key": "shift+cmd+n",
    "command": "explorer.newFolder"
  },
  {
    "key": "ctrl+alt+cmd+u",
    "command": "editor.action.transformToUppercase"
  },
  {
    "key": "ctrl+alt+cmd+l",
    "command": "editor.action.transformToLowercase"
  },
  {
    "key": "shift+alt+cmd+\\",
    "command": "workbench.action.joinAllGroups"
  },
  {
    "key": "alt+cmd+\\",
    "command": "workbench.action.joinTwoGroups"
  },
  {
    "key": "shift+alt+n",
    "command": "workbench.action.navigateForward"
  },
  {
    "key": "ctrl+shift+-",
    "command": "-workbench.action.navigateForward"
  },
  {
    "key": "shift+alt+m",
    "command": "workbench.action.navigateBack"
  },
  {
    "key": "ctrl+-",
    "command": "-workbench.action.navigateBack"
  },
  {
    "key": "ctrl+`",
    "command": "workbench.action.terminal.focus",
    "when": "editorFocus"
  },
  {
    "key": "ctrl+`",
    "command": "workbench.action.focusActiveEditorGroup",
    "when": "terminalFocus"
  },
  {
    "key": "cmd+t",
    "command": "editor.action.insertSnippet",
    "when": "editorTextFocus",
    "args": {
      "snippet": "console.log(${1:${CLIPBOARD}})$0"
    }
  },
  {
    "key": "cmd+u 1",
    "command": "editor.action.insertSnippet",
    "when": "editorTextFocus",
    "args": {
      "snippet": "console.log(${1:${TM_SELECTED_TEXT}})$0"
    }
  },
  {
    "key": "ctrl+c", // 快速给当前选中的文本加console
    "command": "editor.action.insertSnippet",
    "when": "editorTextFocus",
    "args": {
      "snippet": "console.log(${1:${TM_SELECTED_TEXT}})$0"
    }
  },
  {
    "key": "ctrl+s", // 快速插入变量
    "command": "editor.action.insertSnippet",
    "when": "editorTextFocus",
    "args": {
      "snippet": "${1:${TM_SELECTED_TEXT}}: \"\","
    }
  },
  {
    "key": "alt+cmd+ctrl+i", // 将当前文件显示在左侧tabbar
    "command": "workbench.files.action.showActiveFileInExplorer",
    "when": "textInputFocus"
  },
  {
    "key": "alt+cmd+ctrl+o", // 在finder中显示当前文件 Reveal in Finder
    "command": "revealFileInOS",
    "when": "textInputFocus"
  },
  {
    "key": "ctrl+alt+cmd+p", // 拷贝当前文件路径 Copy Path
    "command": "copyFilePath",
    "when": "textInputFocus"
  }
]

5. 一些使用技巧

  1. 在不同的$之间切换用 tab键, 如果想反向切换使用shift +tab键。
  2. ${1:defaultVal} 可以直接设置当前位置的默认值。
  3. ${1|GET,POST,PUT,DELETE,UPDATE|}可以给默认可选项供人选择。其中|之间用逗号分隔的字符为选项
  4. \n换行, \t制表符。 支持转义字符。比如如果想输出this.$message.success("xx")这行代码。 就需要在body中添加"this.\\$message.success(\"xx\")"
  5. 在不同的文件中设置不同的scope可以有效防止出错或混淆,最好设置下。常用的scope有vue, script, css, javascript, typescript, html, json如果不设置, 默认在任何文件中都生效
  6. 如果prefix设置的代码片段名称一致, 不会造成覆盖和报错, 而是会与插件中的同名代码片段和其他同名代码片段同时出现在提示代码中, 所以要写好描述和名称来进行区分。
  7. $0最好在每个代码片段中都设置一下, 否则。会造成无法结束代码片段操作,每次都要多操作一次才能结束。
  8. Trigger Suggest: 当网络比较卡或者你当前的代码片段不显示时, 可以使用trigger suggest触发建议快捷键来查看当前文本的代码片段是什么。 快捷键打开方式(首选项 -> Keyboard Shortcuts)。 这是推荐的做法。 当然也有比较low的做法, 删一个字符串, 也能重新看到代码片段提示。
  9. 重要: 自己写代码片段有时是比较容易出错的且费时费力, 还好有现成的网站, 可以把我们的代码直接生成代码片段 snippet-generator.app/

6. vscode代码片段

这些代码片段是我自己总结出来的, 使用了一些上边所阐述的一些功能和语法,感兴趣的可以直接拷贝到新建代码片段模板中使用。 后期还会不断完善和优化。 主要功能点有

  1. vue自定义基础模板, name可以根据文件名生成
  2. 自定义$.ajax方法, 有选择项
  3. console.log各种特殊提示
  4. 注释模板
  5. 获取当前文件绝对路径
  6. 打印对象

自定义代码文件 snippets-template.code-snippets

具体查看 代码片段文档

{
  /* 自动生成代码片段的网站 snippet-generator.app.  使用用法(vscode): ctrl + shift + p --> 首选项:配置用户代码片段(Preferences: Configure User Snippets) --> 新代码片段. 复制当前文档所有代码 */

  "vueC": {
    "prefix": "vueC",
    "body": [
      "<template>",
      "  <div>",
      "    ${0:${TM_FILENAME_BASE}}",
      "  </div>",
      "</template>",
      "",
      "<script>",
      "export default {",
      "  name: \"${TM_FILENAME_BASE/(.)/${1:/upcase}/}\",",
      "  props: {},",
      "  data() {",
      "    return {",
      "",
      "    }",
      "  },",
      "  components: {},",
      "  computed: {},",
      "  watch: {},",
      "  created() {},",
      "  mounted() {},",
      "  methods: {",
      "",
      "  }",
      "}",
      "</script>",
      "<style scoped lang=\"scss\">",
      "",
      "</style>",
      ""
    ],
    "description": "vue custom template自定义模板"
  },

  "vv": {
    "scope": "vue",
    "prefix": "vv",
    "body": [
      "<template>",
      "  <div>{{ d1 }}</div>",
      "</template>",
      "",
      "<script>",
      "export default {",
      "  name: \"T1\",",
      "  props: {},",
      "  data() {",
      "    return {",
      "      d1: \"t1\"",
      "    };",
      "  },",
      "  components: {},",
      "  computed: {},",
      "  watch: {},",
      "  created() {},",
      "  mounted() {},",
      "  methods: {",
      "    t1() {}",
      "  }",
      "};",
      "</script>",
      "<style scoped lang=\"scss\"></style>",
      ""
    ],
    "description": "vv"
  },
  "vueD": {
    "prefix": "vueD",
    "body": [
      "<template>",
      "  <div>",
      "    <kd-drawer",
      "      v-bind=\"\\$attrs\"",
      "      v-on=\"\\$listeners\"",
      "      ref=\"drawerRef\"",
      "      :title=\"'提示' + fileName\"",
      "      :visible.sync=\"isShow\"",
      "      @confirm=\"confirm\"",
      "    >",
      "      <el-form",
      "        ref=\"formRef\"",
      "        :model=\"form\"",
      "        :rules=\"rules\"",
      "        label-position=\"right\"",
      "        label-width=\"100px\"",
      "      >",
      "        <el-form-item label=\"名称\" prop=\"name\">",
      "          <kd-input v-model=\"form.name\" />",
      "        </el-form-item>",
      "      </el-form>",
      "    </kd-drawer>",
      "  </div>",
      "</template>",
      "",
      "<script>",
      "export default {",
      "  name: \"${TM_FILENAME_BASE/(.)/${1:/upcase}/}\",",
      "  props: {},",
      "  data() {",
      "    return {",
      "      fileName: \"(${TM_FILENAME_BASE/(.)/${1:/upcase}/})\",",
      "      isShow: false,",
      "      form: {",
      "        name: '',",
      "      },",
      "      rules: {",
      "        name: [this.mBlurRequired()],",
      "      },",
      "    }",
      "  },",
      "  components: {},",
      "  computed: {},",
      "  watch: {},",
      "  created() {",
      "    this.open()",
      "  },",
      "  mounted() {},",
      "  methods: {",
      "    open() {",
      "      this.isShow = true;",
      "    },",
      "    confirm() {",
      "      this.\\$refs.formRef.validate((valid) => {",
      "        if (valid) {",
      "          this.isShow = false;",
      "        } else {",
      "          this.\\$pub.\\$toast(\"验证失败\");",
      "        }",
      "      })",
      "    },",
      "  },",
      "}",
      "</script>",
      "<style scoped lang=\"scss\"></style>",
      ""
    ],
    "description": "vueD drawer页面快速生成"
  },

  /*  自定义$.ajax方法 */
  "ajax quick generate": {
    "scope": "javascript,typescript",
    "prefix": "ajax",
    "body": [
      "$.ajax({",
      "\ttype : '${1|GET,POST,PUT,DELETE,UPDATE|}',",
      "\tcontentType: '${2:application/json;charset=UTF-8}',",
      "\turl: '${3: http://127.0.0.1/admin/list}',",
      "\tdata: ${4|[],{}|},",
      "\tsuccess: (${5:res}) => {",
      "\t\tconsole.log(${5:res}, '$5');",
      "\t},",
      "\terror: (${6:err}) => {",
      "\t\tconsole.error(${6:err}, '${6:err}');",
      "\t},",
      "});",
      "$0"
    ],
    "description": "$.ajax quick generate"
  },
  /* console.log 加this */
  "log with this": {
    "scope": "javascript,typescript",
    "prefix": "clt",
    "body": [
      "console.log(`%c this.${1:${CLIPBOARD}} ***** ${TM_LINE_NUMBER}${TM_FILEPATH} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}`, \"background-image:color:transparent;color:blue;font-size:1.2em\");",
      "console.log(this.${1:${CLIPBOARD}});$0"
    ],
    "description": "log with this"
  },
  /* console.error double */
  "log error double": {
    "scope": "javascript,typescript",
    "prefix": "cle",
    "body": ["console.error('${1:defaultVal}', ${1:defaultVal})$0"],
    "description": "console.error double加变量名"
  },
  /* console.warn double */
  "log warn double": {
    "scope": "javascript,typescript",
    "prefix": "cww",
    "body": ["console.warn(${1:defaultVal}, '${1:defaultVal}')$0"],
    "description": "console.warn double加变量名"
  },
  /* 最基础的console.log */
  "log primary": {
    "scope": "javascript,typescript",
    "prefix": "clp",
    "body": ["console.log($1)$0"],
    "description": "最基础console.log"
  },
  /*  醒目的色彩提示console.log 蓝色 */
  "log color": {
    "scope": "javascript,typescript",
    "prefix": "c",
    "body": [
      "console.log(`%c ${1:${CLIPBOARD}} ***** ${TM_LINE_NUMBER}${TM_FILEPATH} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}}`, \"background-image:color:transparent;color:blue;font-size:1.2em\");",
      "console.log(${1:${CLIPBOARD}});$0"
    ],
    "description": "log蓝色代码"
  },
  /*  醒目的色彩提示console.log 蓝色 */
  "log color2": {
    "scope": "javascript,typescript",
    "prefix": "clc",
    "body": [
      "console.log(`%c ${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}}`, 'background:#fff;color:blue', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "log蓝色代码"
  },
  /*  醒目的色彩提示console.log 红色  */
  "log red color": {
    "scope": "javascript,typescript",
    "prefix": "clr",
    "body": [
      "console.log(`%c ${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}}`, 'background:#fff;color:red', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "log红色代码"
  },
  "log purple color": {
    "scope": "javascript,typescript",
    "prefix": "cll",
    "body": [
      "console.log(`%c ${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} ` + '', 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "log在一行打印"
  },
  /*  醒目的色彩提示console.log 绿色 */
  "log green color": {
    "scope": "javascript,typescript",
    "prefix": "clg",
    "body": [
      "console.log(`%c ${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}}`, 'background:#fff;color:green', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "log绿代码"
  },
  /*  醒目的色彩提示console.log  */
  "log yellow color": {
    "scope": "javascript,typescript",
    "prefix": "cly",
    "body": [
      "console.log(`%c ${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}}`, 'background:#fff;color:yellow;font-size:2em;', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "log彩色代码"
  },
  "log base": {
    "scope": "javascript,typescript",
    "prefix": "cc",
    "body": ["console.log(${1:defaultVal});$0"],
    "description": "log_blue"
  },
  /*  醒目的色彩提示console.log  */
  "log blue": {
    "scope": "javascript,typescript",
    "prefix": "cli",
    "body": [
      "console.log(`%c ${1:${CLIPBOARD}} ${TM_LINE_NUMBER}${TM_FILEPATH} `, 'background:#fff;color:blue;font-size:2em;', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "log_blue"
  },

  "log 1": {
    "scope": "javascript,typescript",
    "prefix": "cl1",
    "body": [
      "console.log(`%c 111=>${TM_LINE_NUMBER}${RELATIVE_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 1"
  },
  "log 2": {
    "scope": "javascript,typescript",
    "prefix": "cl2",
    "body": [
      "console.log(`%c 222=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 2"
  },
  "log 3": {
    "scope": "javascript,typescript",
    "prefix": "cl3",
    "body": [
      "console.log(`%c 333=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 3"
  },
  "log 4": {
    "scope": "javascript,typescript",
    "prefix": "cl4",
    "body": [
      "console.log(`%c 444=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 4"
  },
  "log 5": {
    "scope": "javascript,typescript",
    "prefix": "cl5",
    "body": [
      "console.log(`%c 555=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 5"
  },
  "log 6": {
    "scope": "javascript,typescript",
    "prefix": "cl6",
    "body": [
      "console.log(`%c 666=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 6"
  },
  "log 7": {
    "scope": "javascript,typescript",
    "prefix": "cl7",
    "body": [
      "console.log(`%c 777=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 7"
  },
  "log 8": {
    "scope": "javascript,typescript",
    "prefix": "cl8",
    "body": [
      "console.log(`%c 888=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 8"
  },
  "log 9": {
    "scope": "javascript,typescript",
    "prefix": "cl9",
    "body": [
      "console.log(`%c 999=>${TM_LINE_NUMBER}${TM_FILEPATH} ${1:${CLIPBOARD}} `, 'background:#000;color:#bada55', ${1:${CLIPBOARD}});", // name 是无敌的
      "$0"
    ],
    "description": "console 9"
  },
  "log左半边": {
    "scope": "javascript,typescript",
    "prefix": "ch",
    "body": ["console.log($0"],
    "description": "console.log("
  },
  "对象的打印": {
    "scope": "javascript,typescript",
    "prefix": "clo",
    "body": [
      "console.log(`打印对象***** ${1:${CLIPBOARD}} ***** ${TM_LINE_NUMBER}${TM_FILEPATH}  `);",
      "console.log(JSON.stringify(${1:${CLIPBOARD}}, null, '\\t'));"
    ],
    "description": "console 9"
  },
  "打中文": {
    "scope": "javascript,typescript",
    "prefix": "clz",
    "body": [
      "console.log(`***** ${1:99999}  ${TM_LINE_NUMBER}${TM_FILEPATH}  ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}`);"
    ],
    "description": "console 9"
  },
  "ff": {
    "scope": "",
    "prefix": "ff",
    "body": ["/**", "${TM_DIRECTORY}", "${1:${TM_FILEPATH}}$0", "*/"],
    "description": "查看当前文件路径"
  },
  "bs": {
    "scope": "scss,css",
    "prefix": "bs",
    "body": ["box-sizing: border-box;$0"],
    "description": "box-sizing:border-box"
  },
  "d": {
    "scope": "javascript,typescript,vue",
    "prefix": "d",
    "body": ["debugger;$0"],
    "description": "add debugger"
  },
  "r": {
    "scope": "javascript,typescript,vue",
    "prefix": "r",
    "body": ["return $0"],
    "description": "add return"
  },
  "用户信息": {
    // prefix: 在编辑器中输入的此内容时,在编辑器建议中会显示该片段。
    "prefix": "author",
    // TM_FILENAME_BASE : 当前文件名
    // CURRENT_YEAR : 年(4位数)  CURRENT_YEAR_SHORT:年(2位数)  CURRENT_MONTH:月  CURRENT_DATE:日
    // CURRENT_HOUR :小时  CURRENT_MINUTE :分钟 CURRENT_SECOND:秒
    "body": [
      "/**",
      "* 用户信息",
      "* @文件 ${TM_FILENAME_BASE}",
      "* ! author: andy凌云",
      "* ? description: ${1:无}",
      "* TODO: since: 创建时间  ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}",
      "**/$0"
    ],
    // 描述说明,在片段说明中会显示此字段的文本内容。
    "description": "Insert description."
  },
  "wxjs": {
    "scope": "javascript,typescript",
    "prefix": "wx",
    "body": [
      "const app = getApp()",
      "Page({",
      "\tdata: {",
      "\t\t$1",
      "\t},",
      "\tonShow() {",
      "\t\t$2",
      "\t},",
      "\tonReady() {",
      "\t\t$3",
      "\t},",
      "\t$4",
      "$0",
      "})"
    ],
    "description": "微信小程序代码片段"
  },
  "db": {
    "prefix": "db",
    "scope": "vue-html",
    "body": ["<${1:div}>$2</${1:div}>$0"],
    "description": "插入html"
  },
  "w1": {
    "prefix": "w1",
    "scope": "",
    "body": ["width: 100%;", "$0"],
    "description": "width: 100%"
  },
  "pr": {
    "prefix": "pr",
    "scope": "javascript,vue,typescript",
    "body": [
      "${1:${CLIPBOARD}}:{",
      "\ttype: ${2|String,Number,Boolean,Object,Array,Function|},",
      "\tdefault: ${3|\"\",true,false,()=>{},()=>[]|},",
      "},",
      "$0"
    ],
    "description": "custom prop"
  },
  "prs": {
    "prefix": "prs",
    "scope": "javascript,vue,typescript",
    "body": [
      "${1:${CLIPBOARD}}: {",
      "\ttype: String,",
      "\tdefault: \"\"",
      "},",
      "$0"
    ],
    "description": "prop string"
  },
  "pra": {
    "prefix": "pra",
    "scope": "javascript,vue,typescript",
    "body": [
      "${1:${CLIPBOARD}}: {",
      "\ttype: Array,",
      "\tdefault: () => []",
      "},",
      "$0"
    ],
    "description": "prop array"
  },
  "prn": {
    "prefix": "prn",
    "scope": "javascript,vue,typescript",
    "body": ["${1:${CLIPBOARD}}: {", "\ttype: Number,", "},", "$0"],
    "description": "prop array"
  },
  "prb": {
    "prefix": "prb",
    "scope": "javascript,vue,typescript",
    "body": [
      "${1:${CLIPBOARD}}: {",
      "\ttype: Boolean,",
      "\tdefault: ${2:true}",
      "},",
      "$0"
    ],
    "description": "prop boolean"
  },
  "pro": {
    "prefix": "pro",
    "scope": "javascript,vue,typescript",
    "body": [
      "${1:${CLIPBOARD}}: {",
      "\ttype: Object,",
      "\tdefault: () => {}",
      "},",
      "$0"
    ],
    "description": "prop object"
  },

  "vf": {
    "prefix": "vf",
    "scope": "vue-html",
    "body": [
      "<div v-for=\"(v,i) in ${1:${CLIPBOARD}}\" :key=\"i\" class=\"item\">",
      "\t<div>{{${2:v}}}</div>",
      "</div>$0"
    ],
    "description": "vue的for循环"
  },
  "cmd": {
    "prefix": "cmd",
    "scope": "javascript, typescript",
    "body": [
      "/**",
      "* @描述",
      "* ${1:}",
      "* @使用方法",
      "  ${2:}",
      "* @param",
      "* ${3:}",
      "* @LastEditTime: 最后更新时间",
      "* ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
      "* @Author: andy凌云",
      "*/"
    ],
    "description": "自定义文件注释"
  },
  "zs": {
    "prefix": "zs",
    "scope": "",
    "body": [
      "/**",
      " * $1",
      " * @description $2",
      " * @property {String} $3",
      " * @event {Function} $4",
      " * @example $5",
      " */"
    ],
    "description": "自定义文件注释"
  },
  "cmdt": {
    "prefix": "cmdt",
    "scope": "",
    "body": [
      "/**",
      "* @param {*} url 请求接口",
      "* @param {*} params 请求参数",
      "* @param {*} method 请求方式 GET / POST",
      "* @param {*} contentType 内容类型",
      "* @param {*} needLoading  是否需要loading",
      "* @param {*} needIntercept  是否需要添加拦截",
      "*/"
    ],
    "description": "自定义文件注释"
  },
  "tt": {
    "prefix": "tt",
    "scope": "javascript,typescript",
    "body": ["this.\\$pub.${1|$toast,deepClone,uuid,judgeType,isEmpty,parseTime,setStorage,getStorage,clearStorage,debounce,getDates|}(${2:\"${3}\"});"],
    "description": "this.$pub及其对应文本的简写"
  },
  "mm": {
    "prefix": "mm",
    "scope": "javascript,typescript",
    "body": ["this.${1|mBlurRequired,mChangeRequired,mDisabled,mNameLength,mValidateName,mValidateChinese,mValidateMobile,validateNumber|}(${2})"],
    "description": "this.的mixin方法及其对应文本的简写"
  },
  "t": {
    "prefix": "t",
    "scope": "javascript,typescript",
    "body": ["this.${1:${CLIPBOARD}}"],
    "description": "this.$pub.$toast()的简写"
  },
  "td": {
    "prefix": "td",
    "scope": "javascript,typescript",
    "body": ["this.$$pub.deepClone('$1'$2)$0"],
    "description": "this.$pub.deepClone()的简写"
  },
  "tu": {
    "prefix": "tu",
    "scope": "javascript,typescript",
    "body": ["this.$$pub.uuid('$1'$2)$0"],
    "description": "this.$pub.uuid()的简写"
  },

  "http": {
    "prefix": "h",
    "scope": "javascript,typescript",
    "body": [
      "\\$http($1$0).then(res => {",
      "\tconsole.log(`%c res` + '',",
      "\"background-image:color:transparent;color:blue;font-size:2em\");",
      "\tconsole.log(res);",
      "});"
    ],
    "description": "this的简写"
  },
  "ww": {
    "prefix": "ww",
    "body": [
      "watch: {",
      "  ${1:${CLIPBOARD}}(val) {",
      "    this.$2 = val;",
      "  },",
      "},"
    ],
    "description": "ww"
  },
  "m": {
    "prefix": "m",
    "scope": "",
    "body": ["$1($2) {", "\t$0", "},"],
    "description": "vue内部的函数"
  },
  "f": {
    "prefix": "f",
    "scope": "",
    "body": ["function $1($2) {", "\t$0", "}"],
    "description": "函数快捷方式"
  },

  "cmp": {
    "prefix": "cmp",
    "scope": "javascript,typescript",
    "body": ["components: {", "\t$0", "},"],
    "description": "快速生成components"
  },
  "imp": {
    "prefix": "imp",
    "scope": "javascript,typescript",
    "body": ["import $1 from '@/$2$1';$0"],
    "description": "快速important导入组件"
  },
  "ef": {
    "prefix": "ef",
    "scope": "javascript,typescript",
    "body": ["export function $1($2) {", "\t$0", "}"],
    "description": "export导出函数"
  },
  "cp": {
    "prefix": "cp",
    "scope": "scss,css,less",
    "body": ["cursor: pointer;"],
    "description": "cursor: pointer"
  },

  "kkk": {
    "prefix": "kkk",
    "scope": "",
    "body": ["${RANDOM}", "${RANDOM_HEX}", "${UUID}"],
    "description": "测试"
  },
  "next": {
    "prefix": "next",
    "scope": "javascript,typescript,vue",
    "body": ["this.\\$nextTick(() => {", "\t$0", "});"],
    "description": "$nexttick"
  },
  "eb": {
    "prefix": "eb",
    "scope": "vue-html",
    "body": [
      "<el-button @click=\"${1:t1}\" ${2:type=\"${3:primary}\"}>${4:测试}</el-button>$0"
    ],
    "description": "el-button快速生成"
  },
  "测试模板": {
    "prefix": "vueT",
    "body": [
      "<template>",
      "  <div>",
      "    <el-button @click=\"t1\" type=\"primary\">测试1</el-button>",
      "    <el-button @click=\"t2\" type=\"info\">测试2</el-button>",
      "  </div>",
      "</template>",
      "",
      "<script>",
      "export default {",
      "  name: \"${TM_FILENAME_BASE/(.)/${1:/upcase}/}\",",
      "  props: {},",
      "  data() {",
      "    return {",
      "      num: 123,",
      "      str: 'hello world',",
      "      arr: [11, 22, 33],",
      "      obj: {",
      "        name: 'andy',",
      "        age: 18,",
      "        objArr:[{name: 'andy', age: 18}],  ",
      "      },",
      "      date: new Date()",
      "    };",
      "  },",
      "  components: {},",
      "  computed: {},",
      "  watch: {},",
      "  created() {",
      "    this.t1();",
      "  },",
      "  mounted() {},",
      "  methods: {",
      "    t1() {",
      "      console.log('t1');",
      "    },",
      "    t2() {",
      "      console.log('t2');",
      "    }",
      "  }",
      "};",
      "</script>",
      "<style scoped lang=\"scss\"></style>",
      ""
    ],
    "description": "测试模板"
  },

  // kd-component组件快捷生成
  "input": {
    "scope": "vue-html",
    "prefix": "input",
    "body": ["<kd-input v-model=\"$1\" ${2: title=\"${3}\"} />$0"],
    "description": "kd-input快捷生成"
  },
  "drawer": {
    "scope": "vue-html",
    "prefix": "drawer",
    "body": [
      "<kd-drawer v-bind=\"\\$attrs\" v-on=\"\\$listeners\" ref=\"drawerRef\" title=\"$1\" :visible.sync=\"${2:isShow}\" @confirm=\"confirm\">$3</kd-drawer>$0"
    ],
    "description": "kd-drawer快速生成"
  },
  "dialog": {
    "scope": "vue-html",
    "prefix": "dialog",
    "body": [
      "<kd-dialog v-bind=\"\\$attrs\" v-on=\"\\$listeners\" ref=\"dialogRef\" title=\"$1\" :visible.sync=\"${2:isShow}\" @confirm=\"confirm\">$3</kd-dialog>$0"
    ],
    "description": "kd-dialog快速生成"
  },
  "select": {
    "scope": "vue-html",
    "prefix": "select",
    "body": [
      "<kd-select v-model=\"${1}\" :options=\"${2}\" />$0"
    ],
    "description": "kd-select快速生成"
  },
  "jobTree": {
    "scope": "vue-html",
    "prefix": "jobTree",
    "body": [
      "<kd-job-tree ref=\"jobTreeRef\" :defaultProps=\"defaultProps\" :treeData=\"treeData\" @nodeHandler=\"nodeHandler\">",
      "      <template #data=\"{ data }\">",
      "        <div>{{ data.name }}</div>",
      "      </template>",
      "    </kd-job-tree>"
    ],
    "description": "kd-job-tree快速生成"
  },
  "filterTable": {
    "scope": "vue-html",
    "prefix": "filterTable",
    "body": [
      "    <kd-filter-table ref=\"tableRef\" :data=\"${1:tableData}\" :columns=\"${2:columnsData}\" :totalNum=\"totalNum\" @updatePage=\"${3:init}\">$4</kd-filter-table>$0"
    ],
    "description": "kd-filter-table快速生成"
  },
  "tooltiip": {
    "scope": "vue-html",
    "prefix": "tooltip",
    "body": [
      "    <kd-tooltip content=\"${1:测试tooltip}\" ${2:width=\"80px\"} placement=\"bottom\">",
      "      $0",
      "    </kd-tooltip>"
    ],
    "description": "kd-tooltiip快速生成"
  },
  "title": {
    "scope": "vue-html",
    "prefix": "title",
    "body": [
      "<kd-title title=\"$1\">$2</kd-title>$0"
    ],
    "description": "kd-title"
  },
  "form": {
    "prefix": "form",
    "scope": "vue-html",
    "body": [
      "<el-form ref=\"formRef\" :model=\"${1:form}\" :rules=\"${2:rules}\" label-position=\"right\" label-width=\"100px\">",
      "  <el-form-item label=\"${3:名称}\" prop=\"${4:name}\">",
      "    <kd-input v-model=\"${1:form}.${4:name}\" />",
      "  </el-form-item>",
      "</el-form>"
    ],
    "description": "form"
  },
  "range-date": {
    "prefix": "range-date",
    "scope": "vue-html",
    "body": [
      "<kd-date-range v-model=\"${1: dateValue}\" $2 />$0"
    ],
    "description": "kd-range-date快速生成"
  },

  "item": {
    "prefix": "item",
    "body": [
      "<el-form-item label=\"$1\" ${2:prop=\"$3\"}>",
      "  $4",
      "</el-form-item>$0"
    ],
    "description": "item"
  },
  "pl": {
    "prefix": "pl",
    "body": [
      "placeholder=\"$1\" $0",
    ],
    "description": "placeholder快速生成"
  },
  "async": {
    "scope": "javascript",
    "prefix": "async",
    "body": [
      "async ${1:${CLIPBOARD}}() {",
      "    let res = await ${2:${1:${CLIPBOARD}}}();",
      "    ${3:this.${4:tableData}} = res;",
      "},$0"
    ],
    "description": "async await 生成请求方法"
  },
  "im": {
    "scope": "javascript",
    "prefix": "im",
    "body": [
      "import {${1:${CLIPBOARD}}} from \"${2:@/server/$3}\";",
    ],
    "description": "import 快速导入"
  },
  "emit": {
    "prefix": "emit",
    "scope": "javascript, typescript",
    "body": [
      "this.\\$emit(\"${1:update}\");"
    ],
    "description": "emit"
  }
  

}

7. HBuilder X中使用代码片段

在HBuilder X中使用代码片段也很简单。 语法跟vscode差不多。 只是由于代码块设置分为不同的代码块, 所以不需要再有属性scope作用域。 可以复制上边的vscode代码片段, 然后以此选择 工具 -> 代码块设置 -> javascript代码块。 将复制的代码黏贴到自定义代码块(保存后即可生效)。 最后全局替换 \"scope\"\: \"[^"]*\"为空字符串即可使用。

8. webstorm中添加代码片段

webstorm中不能一下子导入所有的代码片段, 只能一个个的添加。 而且语法也跟vscode不一致, 所以要额外处理下。

1. 步骤

  1. command + shift + a
  2. 输入live, 选择 Live Templates
  3. 选择活动面板 -> javascript -> '+'号 -> live-template -> 写代码片段的名称、描述和模板文本 -> 点击定义选择定义在哪些类型文件中 -> 应用

2. 一些需要注意的点或者概念

  1. $变量名$: 在两个$$直接写变量名

  2. $END$: 光标结束位置

  3. 编辑模板变量是主要的处理逻辑的地方。 默认值需要加""双引号, 否则就是取的上下文变量名。 表达式可以有多种效果,可以选择跳过, 那么按tab键就不会顺序跳到跳过的位置。 左下角的箭头可以调整光标移动的顺序。 具体可以看这个链接webstorm模板编辑

  4. 把代码片段配置完以后要选择定义, 在弹出的菜单栏里去勾选当前代码片段在哪些类型的文件中生效。

  5. 有些代码片段, 需要勾选右侧根据风格重新格式化(R), 否则光标可能会无法达到想要的效果

  6. $$中尽量不要写一些保留字符, 否则容易引起冲突, 比如我曾写过$var$就会造成生成代码格式不太对。

  7. 编辑模板变量中的enum表达式会显示一个列表, 你可以从中选择指定的字符串之一, 是很好用的特性。 比如变量method表达式enum('get', 'post', 'delete', 'put')。 然后默认值"post"。 那么就会有默认值post, 四个备选项在列表里供选择。

9. 参考文献

vscode官网: code.visualstudio.com/docs/editor…

segmentfault.com/a/119000001…