Skip to content

视图

视图是 VSCode 扩展的重要组成部分。VSCode 中有两种类型的视图:树视图Webview。请阅读官方用户体验指南以获得基本了解。

在 Manifest 清单中定义

官方文档所述,首先,你需要在 package.jsoncontributes.viewsContainers.[viewContainerType] 部分定义视图容器。然后你可以在 contributes.views.[viewContainerId] 部分定义你的视图。

package.json
json
{
  "contributes": {
    "viewsContainers": {
      "activitybar": [
        {
          "id": "package-explorer",
          "title": "Package Explorer",
          "icon": "resources/package-explorer.svg"
        }
      ]
    },
    "views": {
      "package-explorer": [
        {
          "id": "package-dependencies",
          "name": "Dependencies"
        },
        {
          "id": "package-outline",
          "name": "Outline"
        }
      ]
    }
  }
}

自定义视图容器

注册树视图(TreeView)

树视图(TreeView)用于显示层级数据。你可以使用 useTreeView 函数定义树视图。

这里是一个树视图 (TreeView) 的示例:

ts
import type { TreeViewNode } from 'reactive-vscode'
import { 
computed
,
defineService
,
useTreeView
} from 'reactive-vscode'
import {
TreeItemCollapsibleState
} from 'vscode'
export const
useDemoTreeView
=
defineService
(() => {
function
getRootNode
(
index
: number) {
return {
children
: [
getChildNode
(
index
* 10 + 1),
getChildNode
(
index
* 10 + 2),
],
treeItem
: {
label
: `Root ${
index
}`,
collapsibleState
:
TreeItemCollapsibleState
.
Expanded
,
}, } } function
getChildNode
(
index
: number) {
return {
treeItem
: {
label
: `Child ${
index
}`,
collapsibleState
:
TreeItemCollapsibleState
.
None
,
}, } } const
treeData
=
computed
(() => {
const
roots
: TreeViewNode[] = []
for (let
i
= 1;
i
< 5;
i
++)
roots
.
push
(
getRootNode
(
i
))
return
roots
}) const
view
=
useTreeView
(
'reactive-tree-view',
treeData
,
{
title
: () => `Tree with ${
treeData
.
value
.
length
} roots`,
}, ) // return anything you want to expose return
view
})

然后你可以在任何地方调用 useDemoTreeView 函数来注册树视图并获取返回值:

ts
import { 
defineExtension
} from 'reactive-vscode'
import {
useDemoTreeView
} from './treeView'
export =
defineExtension
(() => {
const
demoTreeView
=
useDemoTreeView
()
// ... })

节点中的 children 属性用于定义节点的子节点。treeItem 属性是必需的,用于定义节点的树项。它应该是一个 TreeItem 对象,或者是一个解析为 TreeItem 对象的 Promise。

如果你想基于一些在 treeData 中未跟踪的响应式值触发更新,你可以将它们传递给 watchSource 选项。

关于 defineServicedefineService 定义的逻辑应该只执行一次,并且可以在多个地方使用。当第一次调用 defineService 传递的函数时,它将在一个分离的 effect scope 中执行,之后的调用将返回缓存的结果。当扩展被停用时,defineService 创建的 effect scope 会自动停止。

WARNING

对于上面的例子,useDemoTreeView不应该在模块的顶层调用,因为在那时扩展上下文不可用。相反,你应该在defineExtension的setup函数中调用它(即当扩展被激活时)。

注册 Webview

Webview用于在编辑器中显示 Web 内容。你可以使用 useWebviewView 函数定义一个 webview。

这里是一个 webview 的示例:

ts
import { 
computed
,
defineService
,
ref
,
useWebviewView
} from 'reactive-vscode'
export const
useDemoWebviewView
=
defineService
(() => {
const
message
=
ref
('')
const
html
=
computed
(() => `
<script> vscode = acquireVsCodeApi() function updateMessage() { vscode.postMessage({ type: 'updateMessage', message: document.querySelector('input').value, }) } </script> <p>${
message
.
value
}</p>
<div style="display:flex; flex-wrap:wrap;"> <input type="text" placeholder="Input Message" /> <button onclick="updateMessage()">Update Message</button> </div> `) const {
postMessage
} =
useWebviewView
(
'reactive-webview-view',
html
,
{
webviewOptions
: {
enableScripts
: true,
enableCommandUris
: true,
},
onDidReceiveMessage
(
ev
) {
if (
ev
.type === 'updateMessage')
message
.
value
=
ev
.message
}, }, ) return {
message
,
postMessage
}
})

调用 useDemoWebviewView 的时机与上一节中的树视图相同。

还有 useWebviewPanel 组合式用于创建 webview 面板。其用法与 useWebviewView 类似。