vscode插件开发入门:小试牛刀

自定义命令

命令可以出发 VSCode 的操作。通过命令,插件可以实现如下所示的功能

  • 把插件的功能开放给用户使用
  • 把插件的功能开放给其他插件使用
  • 把操作绑定到 VSCode 的用户界面(如快捷菜单)
  • 实现内部逻辑

使用 Command

VSCode 包含大量的内置命令,用于与编辑器交互、控制用户界面、执行后台操作等。

  1. 执行 Command
    通过 vscode.commands.executeCommand API 传入 VSCode 或其他插件命令 ID,可以直接执行此 ID 对应的命令。 在下面的例子中,调用 editor.addCommandLine 命令可以对选中的文本添加评论
  2. 此外一些命令需要传入参数,一些命令还会返回结果;
    例如,vscode.openFolder API 用于打开一个文件夹,其中需要传入文件夹路径的 URI,并返回是否成功打开;
  3. Command URI
    命令的 URI 是用于执行命令的链接,是可单击的链接,可以出现在以下 3 个地方
csharp 复制代码
function commentLine() {
    vscode.commands.executeCommand('editor.action.addCommentLine');
}
ini 复制代码
let uri = Uri.file('/some/path/to/folder')
let sucdess = awati commands.executeCommand('vscode.openFolder', uri)
  • 悬停信息的文本
  • 自动补全项的详情区域
  • Webview(网页视图)

命令的 URI 使用 command:格式。例如:editor.action.addCommentLine 命令的 URI 为 command:editor.action.addCommentLine

下面的例子会在悬停界面添加一个 Add comment 的链接

ini 复制代码
class MyHoverProvider implements vscode.HoverProvider{
    provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<vscode.Hover> {
            const commentCommandUri = vscode.Uri.parse('command:editor.action.addCommentLine');

            const contents = new vscode.MarkdownString(`[Add comment](${commentCommandUri})`);

            contents.isTrusted = true;

            return new vscode.Hover(contents);
    }
}

vscode.languages.registerHoverProvider('javascript', new MyHoverProvider());

对于要传参的命令,需要把参数列表以 JSON 数组格式传入,并进行 URI 编码。

下面例子使用 git.stage 命令在悬停界面添加一个 Stage file 的链接

ini 复制代码
class MyHoverProvider implements vscode.HoverProvider{
    provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<vscode.Hover> {

        const args = [{resourceUri: document.uri}];
        const stageCommandUri = vscode.Uri.parse('command:git.stage?${encodeURIComponent(JSON.stringify(args))}');

            const contents = new vscode.MarkdownString(`[Stage file](${stageCommandUri})`);

            contents.isTrusted = true;

            return new vscode.Hover(contents);
    }
}
  1. 内置的 Command
    通过 Ctrl + Shift + P 快捷键打开命令面板,然后输入并执行 Preferences:Open Default Keyboard Shortcuts(JSON)命令,可以打开 keybingdings.json 文件查看完整的命令列表及命令 ID。 此外,我们可以通过快捷键编辑器来获取每一个命令 ID 可以使用一下菜单来打开快捷键编辑器,不同系统下所使用的菜单分别如下所示:
  • Windows/Linux: Fiel -> Preferences -> Keyboard Shortcuts
  • maxOS: Code -> Preferences -> Keyboard Shortcuts

创建 Command

除了使用 VSCode 内置或其他插件的命令,插件还可以创建新的命令,供用户或其他插件使用

  1. 注册 Command
    通过 vscode.registerComand API, 可以把命令 ID 绑定到一个函数上,如下所示:
javascript 复制代码
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
    const command = 'myExtension.sayHello';
    const commandHandler = (name?: string = 'world') => {
        console.log(`Hello ${name}`);
    };

    context.subscriptions.push(vscode.commands.registerCommand(command, commandHandler));
}

// 执行myExtension.sayHello命令时就会调用commandHandler函数
  1. 创建用户可使用的 Command
    为了使终端用户可以在命令面板中调用插件提供的命令,在 package.json 文件的 contributes 贡献点属性中需要定义相应的命令,如下所示:
json 复制代码
{
   "contributes": {
      "commands": [
         {
            "command": "myExtension.sayHello",
            "title": "Say Hello"
         }
      ]
   }
}

通过以上配置,用户可以通过 Ctrl + Shift + P 快捷键打开命令面板, 然后输入并执行 myExtension.sayHello 命令了。

需要注意的是,在命令面板中调用 myExtension.sayHello 命令时,需要确保插件已经激活,可以通过 package.json 文件的 activationEvent 属性设置插件的激活事件,如下所示:

json 复制代码
{
   "activationEvents": ["onCommand:myExtension.sayHello"]
}
  1. 控制 Command 的显示
    默认情况下,所有的命令都会显示在命令面板中,且通过 package.json 文件的 menus.commandPalette 贡献点,可以控制命令的显示条件;
json 复制代码
// 下面的例子中只有用户打开了一个Markdown文件时,myExtension.sayHello命令才会显示在命令面板中。

{
   "contributes": {
      "menus": {
         "commandPalette": [
            {
               "command": "myExtension.sayHello",
               "when": "editorLangId === markdown"
            }
         ]
      }
   }
}

子定义树状视图

定义 View Container

在 package.json 文件中,插件可以通过 contributes.viewsContainers 贡献点来定义新的视图容器,如下所示:

json 复制代码
// 视图容器就是最左侧的图标,比如Explorer Search Folders Source Controll Debug Extenstions等

"contributes": {
  "viewsContainers": {
    "activitybar": [
      {
        "id": "package-explorer",
        "title": "Package Explorer",
        "icon": "media/dep.svg"
      }
    ]
  }
}

定义树状视图

在 package.json 文件中,插件可以通过 contributes.views 贡献点来定义新的树状视图。树状视图可以被定义在以下视图容器中。

  • explorer: 文件资源管理器视图容器
  • debug: 运行与调试视图容器
  • scm: 源代码管理视图容器
  • test: 测试资源管理器视图容器
  • 插件自定义的视图容器
json 复制代码
// 该实例是把nodeDependencies视图放置到了自定义的package-explorer视图容器中

"contributes": {
  "views": {
    "package-explorer": [
      {
        "id": "nodeDependencies",
        "name": "Node Dependencies",
        "when": "explorer"
      }
    ]
  }
}

需要注意的是,在打开视图时需要确保插件已经激活。可以通过 package.json 文件的 activationEvent 属性设置插件的激活事件 onView:${viewId},如下所示:

json 复制代码
{
  "activationEvents": ["onView:nodeDependencies"]
}

树状视图中的操作

在树状视图中,可以在标题栏或快捷菜单中定义相应的操作入口,如下所示

  • view/title: 在视图的标题栏中显示操作入口
  • view/item/context: 在树状视图的节点中显示操作入口
json 复制代码
"contributes": {
  "commands": [
    {
      "command": "nodeDependencies.refreshEntry",
      "title": "Refresh",
      "icon": {
        "light": "resources/light/refresh.svg",
        "dark": "resources/dark/refresh.svg"
      }
    },
    {
      "command": "nodeDependencies.addEntry",
      "title": "Add"
    },
    {
      "command": "nodeDependencies.editEntry",
      "title": "Edit",
      "icon": {
        "light": "resources/light/edit.svg",
        "dark": "resources/dark/edit.svg"
      }
    },
    {
      "command": "nodeDependencies.deleteEntry",
      "title": "Delete"
    },
  ],
  "menus": {
    "view/title": [
      {
        "command": "nodeDependencies.refreshEntry",
        "when": "view == nodeDependencies",
        "group": "navigation"
      },
      {
        "command": "nodeDependencies.addEntry",
        "when": "view == nodeDependencies"
      }
    ]
  },
  "view/item/context": [
    {
      "command": "nodeDependencies.editEntry",
      "when": "view == nodeDependencies && viewItem == dependency",
      "group": "inline"
    },
    {
      "command": "nodeDependencies.deleteEntry",
      "when": "view == nodeDependencies && viewItem == dependency"
    }
  ]
}

TreeDataProvider API

在 package.json 文件中定义好树状视图后,需要在 Typescript/Javascript 文件中通过 TreeDataProvider API 来注册视图,如:

dart 复制代码
vscode.window.registerTreeDataProvider('nodeDependencies', new DepNodeProvider());

TreeView API

如果你需要在视图中实现更复杂的用户界面操作,那么可以使用 window.creatTreeView API,如:

php 复制代码
vscode.window.createTreeView('ftpExplorer', {
    treeDataProvider: new FtpTreeDataProvider(),
});

自定义网页视图

VSCode 没有向插件开发 DOM 的直接控制权限,插件只能通过 VSCode 开发的 API 来定义用户界面。网页视图为插件开发者提供了一个高度可定制化的界面,我们可以把网页视图当做嵌入在 VSCode 中的 iframe. 在编辑器区域中,开发者可以通过前端技术(HTML/CSS/JavaScript)来构建一个用户界面,灵活性非常大

了解 Webview API

创建网页视图

通过 vscode.window.createWebviewPanel 函数,可以创建网页视图,并在编辑器中显示。

通过 webview.html,可以设置网页视图的 HTML 内容

xml 复制代码
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', ()=>{
      // 创建并显示网页视图
      const panel = vscode.window.createWebviewPanel('CatCoding', 'Cat Coding', vscode.ViewColumn.One, {});

      panel.webview.html = getWebviewContent();
    });
  );
}



function getWebviewContent(){
  return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Cat Coding</title>
    </head>
    <body>
      <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" alt="" width="300">
    </body>
    </html>
  `;
}

通过 Ctrl + Shift + P 快捷键打开命令面板,然后输入 Cat Coding: Start cat coding session 命令,即可在网页视图中显示插件中定义的 HTML 页面

更新网页视图中的 HTML 内容

通过改变 webview.html 中的内容,可以动态更新网页视图的页面。此外,通过 title 属性,可以更新网页视图的标题

ini 复制代码
// 下面的例子中,每隔1000毫秒就会更新一次网页视图的页面和标题
import * as vscode from 'vscode';

const cats = {
    'Coding Cat': 'https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
    'Compiling Cat': 'https://media.giphy.com/media/mlvseq9yvZhba/giphy.gif',
    'Testing Cat': 'https://media.giphy.com/media/3oriO0OEd9QIDdllqo/giphy.gif'
};

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', ()=>{
      // 创建并显示网页视图
      const panel = vscode.window.createWebviewPanel('CatCoding', 'Cat Coding', vscode.ViewColumn.One, {});

      let iteration = 0;
      const updateWebview = ()=>{

        const cat = iteration++ % 2 ? 'Compiling Cat' : 'Coding Cat';
        panel.title = cat;
        panel.webview.html = getWebviewContent(cat);
      };


      // 设置初始化的内容
      updateWebview();

      setInterval(updateWebview, 1000);

    });
  );
}


function getWebviewContent(cat){
  return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Cat Coding</title>
    </head>
    <body>
      <img src="${cats[cat]}" alt="" width="300">
    </body>
    </html>
  `;
}

生命周期

网页视图被关闭后会触发 onDidDispose 事件。 在此事件中,我们可以对网页视图的资源进行清理。此外, 我们也可以主动调用 dispose 函数来关闭网页视图。

javascript 复制代码
// 下面的例子会在5000毫秒后自动关闭网页视图
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', ()=>{
      // 创建并显示网页视图
      const panel = vscode.window.createWebviewPanel('CatCoding', 'Cat Coding', vscode.ViewColumn.One, {});

      panel.webview.html = getWebviewContent();

      // 10000毫秒后自动关闭网页视图
      const timeout = setTimeout(()=>panel.dispose(), 10000);

      panel.onDidDispose(
        ()=>{
          clearTimeout(timeout);
        },
        null,
        context.subscriptions
      );
    });
  );
}
显示

当焦点切换到其他标签页时,网页视图会变成隐藏状态,但是并不会被销毁,通过 reveal 函数可以主动显示网页视图;代码如下:

ini 复制代码
export function activate(context: vscode.ExtensionContext) {
    // 记录当前的网页视图对象
    let currentPanel: vscode.WebviewPanel | undefined = undefined;

    // 网页视图
    context.subscriptions.push(
        vscode.commands.registerCommand('catCoding.start', () => {
            const columnToShownIn = vscode.window.activeTextEditor
                ? vscode.window.activeTextEditor.viewColumn
                : undefined;

            if (currentPanel) {
                currentPanel.reveal(columnToShownIn);
            } else {
                // 创建并显示网页视图
                currentPanel = vscode.window.createWebviewPanel(
                    'CatCoding',
                    'Cat Coding',
                    columnToShownIn,
                    {}
                );
            }

            let iteration = 0;
            const updateWebview = () => {
                const cat = iteration++ % 2 ? 'Compiling Cat' : 'Coding Cat';
                panel.title = cat;
                panel.webview.html = getWebviewContent(cat);
            };

            // 设置初始化的内容
            updateWebview();

            setInterval(updateWebview, 3000);

            // 10000毫秒后自动关闭网页视图
            const timeout = setTimeout(() => panel.dispose(), 12000);

            panel.onDidDispose(
                () => {
                    clearTimeout(timeout);
                },
                null,
                context.subscriptions
            );
        })
    );
}
调试网页视图

通过 Ctrl + Shift + P 快捷键打开命令面板,然后输入并执行 Developer: Open Webview Developer Tools 命令,可以打开开发者工具对网页进行调试

加载本地资源

网页视图运行在隔离的环境中。出于安全性的考虑,默认情况下,网页视图不能访问本地资源。为了加载本地的图片、css 或其他资源,需要使用 webview.asWebviewUri 函数

javascript 复制代码
import * as vscode from 'vscode';
import * as path from 'path';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', ()=>{
      // 创建并显示网页视图
      const panel = vscode.window.createWebviewPanel('CatCoding', 'Cat Coding', vscode.ViewColumn.One, {});

      // 获取文件在磁盘上的路径
      const onDiskPath = vscode.Uri.file(path.join(context.extensionPath, 'media', 'python.png'));

      // 转换成适用于网页视图的URI
      const pythonImgSrc = panel.webview.asWebviewUri(onDiskPath);

      panel.webview.html = getWebviewContent(pythonImgSrc);

    });
  );
}

启用 JavaScript

默认情况下,网页视图不能运行 JavaScript 代码。通过 enableScript: true 选项可以启用 JavaScript

xml 复制代码
import * as vscode from 'vscode';
import * as path from 'path';

export function activate(context: vscode.ExtensionContext) {
    context.subscriptions.push(
        vscode.commands.registerCommand('catCoding.start', () => {
            // 创建并显示网页视图
            const panel = vscode.window.createWebviewPanel(
                'CatCoding',
                'Cat Coding',
                vscode.ViewColumn.One,
                {
                    // 在网页视图中启用JavaScript
                    enableScripts: false,
                }
            );

            panel.webview.html = getWebviewContent();
        })
    );
}

function getWebviewContent() {
    return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Cat Coding</title>
    </head>
    <body>
      <h1 id="root"></h1>
      <script>
      const rootContainer = document.querySelector('#root');

      let count = 0;
      setInterval(()=>{
        rootContainer.textContent = count++;
      }, 1000);
      </script>
    </body>
    </html>
  `;
}

消息传递

网页视图与插件是相互独立的运行环境。通过消息传递,两种运行环境可以进行双向通信。

从插件传递数据到网页视图

在插件中,通过 webview.postMessage()函数可以向网页视图(Webview)发送数据。

在网页视图中,通过 message 事件可以监听从插件传过来的数据。

ini 复制代码
// 下面的例子中,catCoding.doRefactor命令调用了postMessage函数,网页视图通过window.addEventListener('message', event=>{ // ... });来处理传来的数据
function getWebviewContent() {
    return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Cat Coding</title>
    </head>
    <body>
      <h1 id="root"></h1>
      <script>
      const rootContainer = document.querySelector('#root');

      let count = 0;
      setInterval(()=>{
        rootContainer.textContent = count++;
      }, 1000);

      // 处理接收到的消息
      window.addEventListener('message', (event)=>{
        const message = event.data;

        switch(message.command){
          case 'refactor':
            count = Math.ceil(count * 0.5);
            rootContainer.textContent = count;
            break;
        }
      })
      </script>
    </body>
    </html>
  `;
}

export function activate(context: vscode.ExtensionContext) {
    // 记录当前的网页视图对象
    let currentPanel: any = undefined;

    // 网页视图
    context.subscriptions.push(
        vscode.commands.registerCommand('catCoding.start', () => {
            if (currentPanel) {
                currentPanel.reveal(vscode.ViewColumn.One);
            } else {
                // 创建并显示网页视图
                currentPanel = vscode.window.createWebviewPanel(
                    'CatCoding',
                    'Cat Coding',
                    vscode.ViewColumn.One,
                    {
                        enableScripts: true,
                    }
                );
            }

            currentPanel.webview.html = getWebviewContent();

            currentPanel.onDidDispose(
                () => {
                    currentPanel = undefined;
                },
                undefined,
                context.subscriptions
            );
        })
    );

    context.subscriptions.push(
        vscode.commands.registerCommand('catCoding.doRefactor', () => {
            if (!currentPanel) {
                return;
            }

            // 把JSON数据发送到网页视图
            currentPanel.webview.postMessage({ command: 'refactor' });
        })
    );
}
从网页视图中将数据传递给插件

从网页视图中,可以通过 acquireVsCodeApi()函数获得 VSCode 的 API 对象,然后使用 vscode.postMessage()函数向插件发送数据。

在插件中,可以通过 webview.onDidReceiveMessage()函数监听从网页视图传来的数据

xml 复制代码
function getWebviewContent() {
    return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Cat Coding</title>
    </head>
    <body>
      <h1 id="root"></h1>
      <script>
      const rootContainer = document.querySelector('#root');
      const vscode = acquireVsCodeApi();

      let count = 0;
      setInterval(()=>{
        rootContainer.textContent = count++;

        // 给插件发送数据
        if(count > 15){
          vscode.postMessage({
            command: 'alert',
            text: 'on line ' + count 
          })
        }
      }, 1000);

      </script>
    </body>
    </html>
  `;
}

export function activate(context: vscode.ExtensionContext) {
    // 网页视图
    context.subscriptions.push(
        vscode.commands.registerCommand('catCoding.start', () => {
            const panel = vscode.window.createWebviewPanel(
                'CatCoding',
                'Cat Coding',
                vscode.ViewColumn.One,
                {
                    enableScripts: true,
                }
            );

            panel.webview.html = getWebviewContent();

            // 处理从网页视图传来的消息
            panel.webview.onDidReceiveMessage(
                message => {
                    switch (message.command) {
                        case 'alert':
                            vscode.window.showErrorMessage(message.text);
                            break;
                    }
                },
                undefined,
                context.subscriptions
            );
        })
    );
}

持久化

当焦点切换到其他标签页时,网页视图会变成隐藏状态。虽然网页视图没有被销毁,但重新获得焦点后页面会被重新渲染,之前的状态也不复存在。

在创建网页视图时,通过设置 retainContextWhenHidden 选项可以解决这个问题:

xml 复制代码
function getWebviewContent() {
    return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Cat Coding</title>
    </head>
    <body>
      <h1 id="root"></h1>
      <script>
      const rootContainer = document.querySelector('#root');

      let count = 0;
      setInterval(()=>{
        rootContainer.textContent = count++;
      }, 1000);
      </script>
    </body>
    </html>
  `;
}

export function activate(context: vscode.ExtensionContext) {
    context.subscriptions.push(
        vscode.commands.registerCommand('catCoding.start', () => {
            // 创建并显示网页视图
            const panel = vscode.window.createWebviewPanel(
                'CatCoding',
                'Cat Coding',
                vscode.ViewColumn.One,
                {
                    // 在网页视图中启用JavaScript
                    enableScripts: true,
                    retainContextWhenHidden: true,
                }
            );

            panel.webview.html = getWebviewContent();
        })
    );
}

集成终端

VSCode 为开发者提供了丰富的集成终端 API,下面介绍部分主要 API

创建终端

ini 复制代码
// 如下所示,通过createTerminal函数可以创建一个新的集成终端
const terminal = vscode.window.createTerminal('my terminal');

在集成终端中运行命令

ini 复制代码
// 如下所示,通过sendText函数可以在集成终端中运行命令
const terminal = vscode.window.createTerminal('my terminal');
terminal.sendText('python /path/to/hello.py');

获取集成终端

通过以下 API 可以获得集成终端实例

  • vscode.window.activeTernimal: 当前活跃的集成终端
  • vscode.window.terminals: 所有打开的集成终端

监听集成终端的事件

通过以下 API 可以监听集成终端事件

  • vscode.window.onDidChangeActiveTerminal: 当前活跃的集成终端被改变
  • vscode.window.onDidCloseTerminal: 有集成终端被关闭
  • vscode.window.onDidOpenTerminal: 有新的集成终端被打开
ini 复制代码
vscode.window.onDidChangeActiveTerminal(e => {
    console.log(`Active terminal changed, name=${e ? e.name : 'undefined'}`);
});

vscode.window.onDidOpenTerminal((terminal: vscode.Terminal) => {
    console.log(`onDidOpenTerminal, name=${terminal.name}`);
});

vscode.window.onDidCloseTerminal((terminal: vscode.Terminal) => {
    console.log(`onDidCloseTerminal, name=${terminal.name}`);
});

存储

在许多场景下都需要使用数据存储,因此 VSCode 提供了多种数据存储方案。

配置项

VSCode 的配置项存储在 setting.json 文件中

json 复制代码
// 在package.json文件中,插件可以定义新的配置项
{
  "contributes": {
    "configuration": {
      "title": "Typescript",
      "properties": {
        "typescript.useCodeSnippetsOnMethodSuggest": {
          "type": "boolean",
          "default": false,
          "description": "Complete functions with their parameter sinature."
        },
        "typescript.tsdk": {
          "type": ["string", "null"],
          "default": null,
          "description": "Specifies the folder path containing the tsserver and lib*.d.ts files to use."
        }
      }
    }
  }

}
访问配置项

在 Typescript/Javascript 文件中,可以通过 vscode.workspace.getConfiguration 访问配置项

ini 复制代码
const config = vscode.workspace.getConfiguration('typescript');
const value = config.get('typescript.useCodeSnippetsOnMethodSuggest');

插件的数据存储

VSCode 为插件提供了数据存储的读写 API,每个插件都有独立的存储空间,主要分为以下两种:

  • ExtensionContext.globalState: 全局范围的存储空间
  • ExtensionContext.workspaceState: 针对当前工作区的存储空间
javascript 复制代码
// 以下是插件的数据存储相关代码样例
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
    const value1 = context.globalState.get('key1');
    context.globalState.update('key2', 'value2');
}

加密的数据存储

VSCode 并未直接提供用于存储加密数据的 API,但是 VScode 包含了 Keytar 软件包,可以让开发者通过操作系统的加密存储来添加、读取、更改、删除机密数据

要使用 Keytar,首先要在 package.json 文件中添加 TypeScript 的类型定义, "devDependencies": { "@types/keytar": "^4.0.1" }

接下来,就可以在 TypeScript/Javscript 文件中过使用 Keytar 了,代码如下:

typescript 复制代码
import * as keytarType from 'keytar';

private _keytar: typeof keytarType;
this._keytar = getCoreNodeModule('keytar');
const token = await this._keytar.getPassword('vscode-docker', 'dockerhub');

function getCoreNodeModule(moduleName: string){
  try{
    return require(`${vscode.env.appRoot}/node_modules.asar/${moduleName}`);
  }catch(err){}

  try{
    return require(`${vscode.env.appRoot}/node_modules/${moduleName}`);
  }catch(err){}

  return null;
}
相关推荐
沉默璇年1 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder1 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727571 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart1 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
会发光的猪。2 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客2 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记2 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Yang.992 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
前端李易安2 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js
红绿鲤鱼2 小时前
React-自定义Hook与逻辑共享
前端·react.js·前端框架