多多读书
1049 字
5 分钟
VSCode插件开发六:树视图其实也没那么难

树视图(Tree View)通常用来展示项目目录列表等视图。与 webview 视图不同的是,webview 视图可以嵌套网页内容,而树视图通过定义树的数据来展示内容。这与 web 开发的流程有所不同,初次接触可能会有点晦涩难懂。今天我来讲解一下树视图的使用。

package.json 配置#

在使用树视图之前,首先需要配置 package.json 文件。

{ // ... "contributes": { "views": { "explorer": [ { "id": "epubTree", "name": "Epub TOC" } ] } } // ... }

上面的配置中,explorer表示项目目录面板,如图所示。

explorer是一个数组,可以定义多个视图。其中,id是注册内容时需要使用的标识符,name是面板上方显示的标题。

除了explorer面板,还可以定义其他 4 种类型的面板,如下所示:

  • debug 调试面板

  • scm 资源控制面板

  • test 测试面板

  • 自定义面板,如图所示,可以自定义 logo 和显示面板。

视图提供器#

配置好 package.json 后,首先要定义一个视图提供器,就是一个类用来定义怎么显示每个节点。下面是一个最基本的结构:

import * as vscode from 'vscode' // 创建一个类 EpubTreeProvider,实现了 TreeDataProvider 接口 export default class EpubTreeProvider implements vscode.TreeDataProvider<vscode.TreeItem> { // 创建一个事件发射器,用于通知树数据发生变化 private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined> = new vscode.EventEmitter< vscode.TreeItem | undefined >() // 定义一个只读的事件,允许外部订阅树数据变化事件 readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined> = this._onDidChangeTreeData.event // 定义刷新方法,用于通知视图数据发生变化 refresh(): void { this._onDidChangeTreeData.fire(undefined) } // 获取树中的单个项目,这里可以定义如何显示单个项目 getTreeItem(element: vscode.TreeItem): vscode.TreeItem { return element } // 获取树的子元素,可以是一个异步操作 getChildren(element?: vscode.TreeItem): Thenable<vscode.TreeItem[]> { // 在这里实现获取树的子元素的逻辑 // 可以返回一个 Promise 来异步获取子元素 // 如果没有子元素,可以返回一个空数组 // 在实际使用中,你需要根据你的插件逻辑来实现这个方法 } }

上述代码中,getTreeItemgetChildren方法是视图提供器必须提供的方法,因为内部程序在创建视图时会调用这两个方法。

注册提供器#

视图提供器类定义好之后,如何调用这个类呢?你不需要调用里面的方法自行创建,只需要注册让内部程序去调用。有两种注册方式。

  1. vscode.window.registerTreeDataProvider
vscode.window.registerTreeDataProvider('epubTree', new EpubTreeProvider())
  1. vscode.window.createTreeView
vscode.window.createTreeView('epubTree', { treeDataProvider: new EpubTreeProvider(), })

显示内容#

注册完成后,需要显示内容。只需在getChildren方法中添加数据。例如,添加一个简单的数据:

return new Promise((resolve, reject) => { resolve([new vscode.TreeItem('Hello World!', vscode.TreeItemCollapsibleState.None)]) })

getChildren方法的处理逻辑是:当没有传入element时,返回树的顶层节点。当父节点默认展开或点击某个父节点时,会再次调用getChildren方法,并传入父节点。你只需根据传入的element进行数据处理即可。例如,对上述代码进行修改:

return new Promise((resolve, reject) => { if (!element) { resolve([new vscode.TreeItem('Hello World!', vscode.TreeItemCollapsibleState.Expanded)]) } else { resolve([new vscode.TreeItem('happy coding', vscode.TreeItemCollapsibleState.None)]) } })

结果如下所示:父节点是”Hello World!”,子节点是”happy coding”。

第一个参数 label#

实际上,第一个参数也可以是vscode.Uri类型,此时节点表示一个文件。例如,将”happy coding”修改如下:

vscode.Uri.file('index.html')

结果将如下所示:

在节点前面会自动添加 html 图标。当然,你也可以自定义前面的图标,只需修改 TreeItem 对象的iconPath属性。例如,添加如下代码到getTreeItem方法中即可自定义图标:

element.iconPath = { light: path.join(__filename, '..', '..', 'resources', 'light', 'dependency.svg'), dark: path.join(__filename, '..', '..', 'resources', 'dark', 'dependency.svg'), }

第二个参数 collapsibleState#

第二个参数参数是节点的展开状态。

  • vscode.TreeItemCollapsibleState.Expanded表示节点是展开的。
  • vscode.TreeItemCollapsibleState.Collapsed表示节点是闭合的。
  • vscode.TreeItemCollapsibleState.None表示没有展开与否的状态,如文件。

树视图从定义到展示今天就到这里,后面继续会讲怎么自定义侧边栏的树视图和 webview 视图,以及如何添加刷新、删除等按钮。

VSCode插件开发六:树视图其实也没那么难
https://fuwari.vercel.app/posts/20230905/
作者
我也困了
发布于
2023-09-05
许可协议
CC BY-NC-SA 4.0