To manage a webview, create a dedicated class (e.g., HelloWorldPanel) to handle the lifecycle, state, and HTML content. This prevents resource leaks and centralizes webview logic.
Key responsibilities of the class:
- Singleton Management: Use a static
currentPanel property to track if a panel is already open. - Rendering: Use
vscode.window.createWebviewPanel to create the panel and panel.reveal() to show it if it already exists. - Cleanup: Implement a
dispose() method that clears the static reference, disposes of the vscode.WebviewPanel, and iterates through any internal _disposables to clean up resources. - Lifecycle Hook: Listen to
this._panel.onDidDispose in the constructor to trigger the class's dispose() method when the user closes the webview tab. - Content Injection: Use a private method (e.g.,
_getWebviewContent()) to return the HTML string, which is then assigned to this._panel.webview.html.
import * as vscode from "vscode";
export class HelloWorldPanel {
public static currentPanel: HelloWorldPanel | undefined;
private readonly _panel: vscode.WebviewPanel;
private _disposables: vscode.Disposable[] = [];
private constructor(panel: vscode.WebviewPanel) {
this._panel = panel;
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
this._panel.webview.html = this._getWebviewContent();
}
public static render() {
if (HelloWorldPanel.currentPanel) {
HelloWorldPanel.currentPanel._panel.reveal(vscode.ViewColumn.One);
} else {
const panel = vscode.window.createWebviewPanel(
"hello-world",
"Hello World",
vscode.ViewColumn.One,
{}
);
HelloWorldPanel.currentPanel = new HelloWorldPanel(panel);
}
}
public dispose() {
HelloWorldPanel.currentPanel = undefined;
this._panel.dispose();
while (this._disposables.length) {
const disposable = this._disposables.pop();
if (disposable) {
disposable.dispose();
}
}
}
private _getWebviewContent() {
return /*html*/ `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
`;
}
}