我不知道的 VSCode 扩展:菜单与视图的魔法

652 字 12 min read
前端开发 VSCode 扩展开发 菜单 视图 状态栏

引言

✨ 在上一篇文章中,我们一起迈出了 VSCode 扩展开发的第一步。现在,让我们继续深入探索,学习如何为你的扩展添加更丰富的用户界面元素,例如右键菜单树视图状态栏。这些元素能够极大地提升扩展的易用性和交互性,让你的扩展更加强大和用户友好。今天,就让我们一起揭开 VSCode 扩展中菜单与视图的魔法!

右键菜单 (Context Menu):指尖的魔法

🖱️ 右键菜单 (Context Menu),也称为上下文菜单,是用户界面中非常常见且实用的元素。通过右键点击,用户可以快速访问与当前上下文相关的操作。在 VSCode 扩展中,添加右键菜单可以极大地提升用户操作效率。

添加右键菜单

🧩 要为 VSCode 扩展添加右键菜单,我们需要在 package.json 文件中配置 menus contributes

{
  "contributes": {
    "menus": {
      "editor/context": [ // 编辑器上下文菜单
        {
          "command": "extension.helloWorld", // 关联的命令
          "group": "z_我的扩展", // 菜单分组,用于排序
          "when": "editorFocus" // 菜单显示条件
        }
      ],
      "explorer/context": [ // 资源管理器上下文菜单
        {
          "command": "extension.myExplorerCommand",
          "group": "navigation"
        }
      ]
    }
  }
}
  • menus: 定义菜单 contributes。
  • editor/context: 编辑器上下文菜单的位置。当用户在编辑器中右键点击时,会显示此菜单。
  • explorer/context: 资源管理器上下文菜单的位置。当用户在资源管理器中右键点击文件或文件夹时,会显示此菜单。
  • command: 指定点击菜单项时执行的命令 ID,需要提前在 commands contributes 中注册。
  • group: 菜单分组,用于控制菜单项在菜单中的排序位置。分组名称相同的菜单项会放在一起,并按照分组名称的字母顺序排序。通常使用 数字_分组名称 的格式,例如 1_编辑2_导航z_我的扩展 等。
  • when: 菜单项的显示条件,使用 When Clause Contexts 定义。例如,editorFocus 表示只有当编辑器获得焦点时才显示此菜单项。

示例:添加 "Hello World" 到编辑器右键菜单

📝 假设我们已经注册了一个命令 extension.helloWorld (参考上一篇文章)。现在,我们想将这个命令添加到编辑器的右键菜单中。

  1. 修改 package.json: 在 contributes.menus.editor/context 中添加配置:

    {
      "contributes": {
        "menus": {
          "editor/context": [
            {
              "command": "extension.helloWorld",
              "group": "z_我的扩展",
              "when": "editorFocus"
            }
          ]
        }
      }
    }
    
  2. 重新加载扩展: 按下 Ctrl+Shift+P (或 Cmd+Shift+P on macOS) 打开命令面板,输入 Reload Window 并执行,重新加载 VSCode 窗口,使配置生效。

  3. 测试: 打开一个文件,在编辑器中右键点击,你将在右键菜单的 "z_我的扩展" 分组下看到 "Hello World" 菜单项。点击该菜单项,将会执行 extension.helloWorld 命令,弹出 "Hello World" 消息框。

树视图 (TreeView):结构化的信息展示

🌲 树视图 (TreeView) 是一种常用的用户界面组件,用于以树状结构展示层级数据。在 VSCode 扩展中,树视图非常适合展示文件目录、项目结构、自定义数据等信息。

添加树视图

🏗️ 要为 VSCode 扩展添加树视图,我们需要使用 viewsContainersviews 两个 contributes,在 package.json 文件中进行配置。

{
  "contributes": {
    "viewsContainers": { // 视图容器
      "explorer": [ // 放置在资源管理器视图容器中
        {
          "id": "myTreeViewContainer", // 容器 ID
          "title": "我的树视图", // 容器标题
          "icon": "$(file-directory)" // 容器图标 (使用 VSCode 内置图标)
        }
      ]
    },
    "views": { // 视图
      "myTreeViewContainer": [ // 放置在 "myTreeViewContainer" 容器中
        {
          "id": "myTreeView", // 视图 ID
          "name": "示例树视图", // 视图名称 (显示在视图标题栏)
          "type": "tree", // 视图类型,固定为 "tree"
          "command": "myTreeView.reveal" // (可选) 点击视图标题栏 "更多操作" 菜单时执行的命令
        }
      ]
    }
  }
}
  • viewsContainers: 定义视图容器。视图容器是树视图的载体,可以放置在 VSCode 侧边栏的不同位置,例如资源管理器 (explorer)、调试 (debug) 等。
    • explorer: 将视图容器放置在资源管理器视图容器中。
    • id: 视图容器的唯一 ID。
    • title: 视图容器的标题,显示在侧边栏。
    • icon: 视图容器的图标,可以使用 VSCode 内置图标,也可以使用自定义图标。VSCode 内置图标列表参考 Product Icon Reference
  • views: 定义视图。
    • myTreeViewContainer: 指定视图所属的视图容器 ID。
    • id: 视图的唯一 ID。
    • name: 视图的名称,显示在视图标题栏。
    • type: 视图类型,固定为 "tree"
    • command: (可选) 点击视图标题栏 "更多操作" 菜单时执行的命令。通常用于 "Reveal in Explorer" 或 "Refresh" 等操作。

实现 TreeDataProvider

👨‍💻 仅在 package.json 中配置树视图是不够的,我们还需要提供树视图的数据。为此,我们需要实现 TreeDataProvider 接口,并将其注册到 VSCode。。

import * as vscode from 'vscode';

// 定义树视图的数据项类型
interface TreeItemData {
    label: string;
    children?: TreeItemData[];
}

// 实现 TreeDataProvider 接口
class MyTreeDataProvider implements vscode.TreeDataProvider<TreeItemData> {
    private data: TreeItemData[];

    constructor() {
        this.data = [
            { label: 'Item 1', children: [{ label: 'Sub Item 1' }, { label: 'Sub Item 2' }] },
            { label: 'Item 2' },
            { label: 'Item 3', children: [{ label: 'Sub Item 3' }] }
        ];
    }

    getTreeItem(element: TreeItemData): vscode.TreeItem | Thenable<vscode.TreeItem> {
        const treeItem = new vscode.TreeItem(element.label, element.children ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None);
        return treeItem;
    }

    getChildren(element?: TreeItemData | undefined): vscode.ProviderResult<TreeItemData[]> {
        if (!element) {
            return this.data; // 根节点
        }
        return element.children; // 子节点
    }
}

export function activate(context: vscode.ExtensionContext) {
    // ...

    // 注册 TreeDataProvider
    const treeDataProvider = new MyTreeDataProvider();
    vscode.window.registerTreeDataProvider('myTreeView', treeDataProvider);
}
  • TreeDataProvider<T>: 接口,T 是树视图数据项的类型。
  • getTreeItem(element: T): 返回指定数据项 element 对应的 TreeItem 对象。TreeItem 用于描述树视图的节点,包括标签、图标、展开状态等。
  • getChildren(element?: T): 返回指定数据项 element 的子节点数组。如果 elementundefined,则返回根节点数组。

示例:创建简单的示例树视图

📝 按照上述步骤,我们创建了一个简单的示例树视图,展示了预定义的数据。

  1. 修改 package.json: 添加 viewsContainersviews contributes 配置 (参考上面的代码示例)。

  2. 实现 MyTreeDataProvider: 创建 MyTreeDataProvider 类并实现 TreeDataProvider 接口 (参考上面的代码示例)。

  3. 注册 TreeDataProvider: 在 activate 函数中注册 MyTreeDataProvider

  4. 重新加载扩展: 重新加载 VSCode 窗口。

  5. 查看树视图: 在 VSCode 侧边栏资源管理器视图容器中,你将看到名为 "我的树视图" 的容器,展开后可以看到 "示例树视图",其中展示了我们预定义的数据。

状态栏 (Status Bar):随时可见的信息展示

📢 状态栏 (Status Bar) 位于 VSCode 窗口底部,用于展示全局性的状态信息和提供快速操作入口。在 VSCode 扩展中,使用状态栏可以方便地向用户展示扩展的运行状态、重要信息,并提供常用的快捷操作。

创建和管理状态栏

🛠️ 要创建和管理状态栏,我们需要使用 vscode.window.createStatusBarItem() 方法。

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
    // ...

    // 创建状态栏项目
    const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
    statusBarItem.text = "$( Smiley ) Hello Status Bar"; // 状态栏文本,可以使用 VSCode 内置图标
    statusBarItem.tooltip = "This is a status bar item"; // 鼠标悬停提示
    statusBarItem.command = "extension.helloWorld"; // 点击状态栏项目时执行的命令
    statusBarItem.show(); // 显示状态栏项目

    context.subscriptions.push(statusBarItem); // 将状态栏项目添加到 context.subscriptions,以便在插件卸载时自动销毁
}
  • vscode.window.createStatusBarItem(alignment, priority): 创建状态栏项目。
    • alignment: 状态栏项目在状态栏中的对齐方式,vscode.StatusBarAlignment.Left (左对齐) 或 vscode.StatusBarAlignment.Right (右对齐)。
    • priority: 状态栏项目的优先级,数字越小优先级越高,优先级高的项目会更靠近状态栏的边缘显示。
  • statusBarItem.text: 状态栏显示的文本。可以使用纯文本,也可以使用 VSCode 内置图标,例如 $( Smiley ) 表示笑脸图标。
  • statusBarItem.tooltip: 鼠标悬停在状态栏项目上时显示的提示文本。
  • statusBarItem.command: 点击状态栏项目时执行的命令 ID。
  • statusBarItem.show(): 显示状态栏项目。
  • context.subscriptions.push(statusBarItem): 将状态栏项目添加到 context.subscriptions,VSCode 会在扩展卸载时自动销毁这些资源,避免内存泄漏。

示例:创建简单的状态栏项目

📝 按照上述步骤,我们创建了一个简单的状态栏项目,显示文本和图标,并关联了一个命令。

  1. activate 函数中创建状态栏项目: 使用 vscode.window.createStatusBarItem() 创建状态栏项目,并设置 text, tooltip, command 等属性 (参考上面的代码示例)。

  2. 显示状态栏项目: 调用 statusBarItem.show() 方法显示状态栏项目。

  3. 添加到 context.subscriptions: 将状态栏项目添加到 context.subscriptions

  4. 重新加载扩展: 重新加载 VSCode 窗口。

  5. 查看状态栏: 在 VSCode 窗口底部状态栏的右侧,你将看到我们创建的状态栏项目,显示 "😊 Hello Status Bar"。鼠标悬停时显示提示 "This is a status bar item"。点击状态栏项目,将会执行 extension.helloWorld 命令。

总结

🎉 恭喜你,又掌握了 VSCode 扩展开发的两个重要技巧:添加右键菜单创建树视图,以及如何使用 状态栏 展示信息。通过灵活运用这些技巧,你可以为你的 VSCode 扩展打造更加完善的用户界面,提升用户体验。在下一篇文章中,我们将继续探索 VSCode 扩展的更多高级功能,例如 Webview 和 Output Channel,敬请期待!