背景

想必每个纯熟的前端弄潮者,在纯熟业务之后,经常都会将组件进行抽离公共组件,能够大大的进步开发效率。然而抽离公共组件之后,日常的开发便是创立雷同的文件夹,批改router ,批改表单的属性 fieldsprop 等,反复的创立雷同的文件夹,反复批改文件 name , 反复的写 router 等,然而作为组内不同的人员,格调又不统一,所以能不能即标准代码的格调,又能疾速的创立模板呢。

比方咱们常见的模板类型

├─componentsName│   ├─api│   │  index.js│        ├─components│        │     list-table.vue│        │     list-search.vue│        │     index.js│        ├─config│        │     index.js│   index.vue│   route.js

vscode插件

通过 官网文档 的学习,咱们能够发现 vscode 插件扩大的形式,去实现这个性能。

  • 环境装置
npm i -g yo generator-code // 官网插件开发脚手架yo code // 执行脚手架命令

依据步骤咱们抉择创立 New Extension

能够抉择本人喜爱的语言 Javascript 或者 TypeScript , 这边笔者选的是 JavaScript

同样,咱们从国际惯例的 Hello World 开始,抉择好相应的配置

我的项目构造

我的项目构造比较简单,次要的文件为 package.jsonextension.js 这两个文件

{    "name": "hello-world", // 插件名称    "displayName": "Hello World",    "description": "hello world",    "version": "0.0.1", // 插件版本    "engines": {        "vscode": "^1.63.0" // vscode的版本    },    "categories": [        "Other"    ],  // 扩大的激活事件    "activationEvents": [        "onCommand:hello-world.helloWorld"    ],  // 入口文件    "main": "./extension.js",  // vscode插件大部分性能配置都在这里配置    "contributes": {        "commands": [            {                "command": "hello-world.helloWorld",                "title": "Hello World"            }        ]    },    "scripts": {        "lint": "eslint .",        "pretest": "npm run lint",        "test": "node ./test/runTest.js"    },    "devDependencies": {        "@types/vscode": "^1.63.0",        "@types/glob": "^7.1.4",        "@types/mocha": "^9.0.0",        "@types/node": "14.x",        "eslint": "^7.32.0",        "glob": "^7.1.7",        "mocha": "^9.1.1",        "typescript": "^4.4.3",        "@vscode/test-electron": "^1.6.2"    }}

extension.js 文件内容如下

// The module 'vscode' contains the VS Code extensibility API// Import the module and reference it with the alias vscode in your code belowconst vscode = require('vscode');// this method is called when your extension is activated// your extension is activated the very first time the command is executed/** * @param {vscode.ExtensionContext} context */function activate(context) {    // Use the console to output diagnostic information (console.log) and errors (console.error)    // This line of code will only be executed once when your extension is activated    console.log('Congratulations, your extension "hello-world" is now active!');    // The command has been defined in the package.json file    // Now provide the implementation of the command with  registerCommand    // The commandId parameter must match the command field in package.json    let disposable = vscode.commands.registerCommand('hello-world.helloWorld', function () {        // The code you place here will be executed every time your command is executed        // Display a message box to the user        vscode.window.showInformationMessage('Hello World from Hello World!');    });    context.subscriptions.push(disposable);}// this method is called when your extension is deactivatedfunction deactivate() {}module.exports = {    activate,    deactivate}

1.  了解

  • main 定义了整个插件的主入口,所以看到这里,依照咱们的惯性,能够新建 src 文件夹,将 extension.js 已到 src 文件夹上面。
  • contributes.commands 注册了名为 hello-world.helloWorld 的命令,并在 src/extension.js 实现。
  • 定义完命令之后,还须要在 activationEvents 上增加 onCommand:hello-world.helloWorld

2. 运行调试

新建实现之后,工程曾经帮咱们配置好调试参数

咱们只须要点击 Run Extension 即可,此时将关上一个新的vscode 窗口,显示Extension Development Host

此时咱们按下快捷键 command + shift + P ,输出 Hello 即可看到咱们编写的插件了,选中咱们的插件,即可发现右下角的弹窗 Hello World from Hello World!

3. 增加快捷键和右键菜单

在咱们的 package.json 中,增加如下代码

"contributes": {        "commands": [            {                "command": "hello-world.helloWorld",                "title": "Hello World"            }        ],    "keybindings": [      {        "command": "hello-world.helloWorld",        "key": "ctrl+f10",        "mac": "cmd+f10",        "when": "editorFocus"      }    ],    "menus": {      "explorer/context": [        {          "command": "hello-world.helloWorld",          "group": "navigation", // 菜单位于最下面          "when": "explorerResourceIsFolder" // 只有是文件夹时能力唤起菜单        }      ]    }    },

在文件夹区域右键,即可看到咱们的菜单命令了, 同时也能够看到快捷键。

至此,咱们曾经实现了一个简略的 vscode 插件。

4. 革新

批改文件目录如下

├─node_modules├─src│   main.js├─test│ .eslintrc.json│ .gitignore│ .vscodeignore│ jsconfig.json│ package-lock.json│ package.json│    READEME.md│ vsc-extension-quickstart.md

批改 package.json 文件

{    "name": "hello-template",    "displayName": "hello-template",    "description": "hello world",  "publisher": "retrychx",    "version": "0.0.1",    "engines": {        "vscode": "^1.63.0"    },    "categories": [        "Other"    ],    "activationEvents": [        "onCommand:hello-template"    ],    "main": "./src/main.js",    "contributes": {        "commands": [            {                "command": "hello-template",                "title": "Hello Template"            }        ],    "keybindings": [      {        "command": "hello-template",        "key": "ctrl+f10",        "mac": "cmd+f10",        "when": "editorFocus"      }    ],    "menus": {      "explorer/context": [        {          "command": "hello-template",          "group": "navigation",           "when": "explorerResourceIsFolder"        }      ]    }    },    "scripts": {        "lint": "eslint .",        "pretest": "npm run lint",        "test": "node ./test/runTest.js"    },    "devDependencies": {        "@types/vscode": "^1.63.0",        "@types/glob": "^7.1.4",        "@types/mocha": "^9.0.0",        "@types/node": "14.x",        "eslint": "^7.32.0",        "glob": "^7.1.7",        "mocha": "^9.1.1",        "typescript": "^4.4.3",        "@vscode/test-electron": "^1.6.2"    }}

批改 src/main.js 文件

// The module 'vscode' contains the VS Code extensibility API// Import the module and reference it with the alias vscode in your code belowconst vscode = require('vscode');// this method is called when your extension is activated// your extension is activated the very first time the command is executed/** * @param {vscode.ExtensionContext} context */function activate(context) {    // Use the console to output diagnostic information (console.log) and errors (console.error)    // This line of code will only be executed once when your extension is activated    console.log('Congratulations, your extension "hello-world" is now active!');    // The command has been defined in the package.json file    // Now provide the implementation of the command with  registerCommand    // The commandId parameter must match the command field in package.json    let disposable = vscode.commands.registerCommand('hello-template', function () {        // The code you place here will be executed every time your command is executed        // Display a message box to the user        vscode.window.showInformationMessage('test');    });    context.subscriptions.push(disposable);}// this method is called when your extension is deactivatedfunction deactivate() {}module.exports = {    activate,    deactivate}

registerCommand 办法处,批改命令,和 package.json 中的 command 中保持一致,而后调试运行咱们的 vscode ,快捷键号召出咱们的插件,能够看到咱们的插件名称 Hello Template ,点击,即可看到跳出的弹窗

5. 新建模板字符串

src/ 上面,咱们新建 template.js 文件,在外面申明咱们要新建的模板。

  • route.js 模板

因为须要路由名称和题目两个变量,所以申明了两个变量

const routeTemplate = params => `import List from './index'export default [  {    path: '${params.path}',    name: '${params.path}',    meta: {      title: '${params.title}'    },    component: List  }]`
  • index.js 入口文件模板
const indexTemplate = `<template>  <div></div></template><script>import { ListSearch, ListTable } from './components'import * as API from './api/index'import utils from '@/utils'export default {  components: { ListSearch, ListTable },  data() {    return {      },    }  },  mounted() {  },  methods: {  },}</script><style></style>`

依据封装的组件,所以能够顺次新建不同的模板:configTemplateapiTemplatecomIndexTemplatesearchTemplatetableTemplate 等,导出咱们须要的模板

const config = {  routeTemplate: routeTemplate,  indexTemplate: indexTemplate,  configTemplate: configTemplate,  apiTemplate: apiTemplate,  comIndexTemplate: comIndexTemplate,  searchTemplate: searchTemplate,  tableTemplate: tableTemplate}module.exports = config

6. 引入用户变量

因为咱们须要异步解决,所以引入async

let disposable = vscode.commands.registerCommand('hello-template', async url => {         // 设置输入框提醒     const options = {      prompt: '请输出模板名称',      placeHolder: '模板名称'    }    // 输出模板名称    const templateName = await vscode.window.showInputBox(options)        // 设置题目    const optionsTitle = {      prompt: '请输出题目名称',      placeHolder: '题目名称'    }    // 输出模板名称    const templateTitle = await vscode.window.showInputBox(optionsTitle)    // 设置门路    const optionsRoute = {      prompt: '请输出门路名称',      placeHolder: '门路名称'    }    // 输出门路名称    const templateRoute = await vscode.window.showInputBox(optionsRoute)        const params = {      path: templateRoute,      title: templateTitle    }    });

运行调试,咱们能够看到调用咱们的插件,能够看到呈现了输入框:

通过输出名称,咱们能够拿到本人想要的变量。而后咱们就能够调用 fspath 两个模块就能够写咱们本人的文件了。

因为为了保障,咱们的创立文件和文件夹的程序。

首先咱们用了 existsSyncmkdirSync 来创立文件夹;而后咱们再用 existsSyncwriteFileSync 来创立文件,而后再最初,做个胜利的提醒即可:

vscode.window.showInformationMessage('模板创立胜利')

至此,咱们曾经实现了所有的编码。那么咱们就看一下最初的调试后果。

在文件夹处右键,号召出咱们的插件指令Hello Template

输出对应的名称之后,咱们能够看到在右键的文件夹下,创立了咱们想要的模板。

咱们就能够节俭很多反复的工作了。

7. 引入新性能

因为在开发过程中,后端给的开发文档,提供的接口都是来自mock的连贯,这个时候就在想能不能解析mock的接口数据主动引入接口正文。

const request = require('request')const YAPIURL = 'https://mock.shizhuang-inc.com/api/interface/get'const param = 'token' // 集体的tokenfunction getYapi(id) {  const url = `${YAPIURL}?id=${id}&token=${param}`  return new Promise(async (resolve, reject) => {      request(url, function(error, response,body) {      debugger      if(error) {        reject(error)      }      const bodyToJson = JSON.parse(body)      // 接口id不存在      if(!bodyToJson.data) {        reject(null)      }      resolve({        title: bodyToJson.data.title,        path: bodyToJson.data.path      })    })  })}module.exports = {  getYapi}
  • 增加右键菜单

package.json 外面

"menus": {      "editor/context": [        {          "when": "resourceLangId == javascript", // 当文件为js文件的时候          "command": "erp-addInterface",          "group": "navigation"        }      ]    }

main.js 中,注册command事件

let addDisposable = vscode.commands.registerCommand('erp-addInterface', async url => {     // 设置输入框提醒     const options = {      prompt: '请输出接口Id',      placeHolder: '接口Id'    }    // 输出门路名称    const apiTag = await vscode.window.showInputBox(options)    if(!+apiTag) {      vscode.window.showInformationMessage('输出正确的接口Id')      return    }    try {      const res = await api.getYapi(+apiTag)      const apiName = res.path ? res.path.split('/').pop() : ''      res.name = apiName      const interfaceTemplate = config.interfaceTemplate(res)      await fs.appendFileSync(url.path, interfaceTemplate, 'utf8')      vscode.window.showInformationMessage('接口增加胜利')    } catch (error) {      if(!error) {        vscode.window.showInformationMessage('接口Id不存在')        return      }      vscode.window.showInformationMessage(error)    }
  • 查看成果

能够生成正文和接口,方便快捷。

打包

无论是本地打包还是公布到利用市场,咱们都要借助vsce 这个工具。

1. 装置

npm install vsce -g

2. 打包

打包成 vsix 文件

vsce package

发现报错如下:

谬误指出咱们要批改 README.md 文件,咱们批改以下文件,再次执行打包。

依照批示命令,一步步的执行,打包胜利,看一下咱们的我的项目目录,能够看到咱们的打包文件。

3. 公布

关上公布市场 官方网站 , 创立本人的公布账号,而后记录下本人的集体 token, 即可开始公布。

vsce publish

输出本人的账号,和 token 之后就能够公布了。期待几分钟后就能够在网页看到本人的我的项目

例如笔者公布的插件 erp-template ,在插件市场搜寻能够看到,咱们本人的插件了

好了,至此,vscode 插件开发曾经实现了。

总结

这里仅仅是想到的一个开发场景,相对来说,只是提供一个开发思路,在开发过程中,能够多进行思考,做一些乏味的事件。

文/migor

关注得物技术,做最潮技术人!