vscode插件开发-在活动栏注册webview

714 阅读1分钟

实现效果:在侧边栏的explorer上加一个视图,视图内展示一个webview

image.png

下面将会介绍到

  • 向explorer添加一个webview视图.
  • webview与wxtension的相互通信
  • webview的数据持久化.
  • 添加一条命令到view title.

package.json里的配置

vscode注册的命令,视图。必须在package.json中再注册一遍

"contributes": {
		"views": {
			"explorer": [
				{
					"type": "webview",//指定类型
					"id": "calicoColors.colorsView",//后面要靠这个id进行webview注册
					"name": "Calico Colors"
				}
			]
		},
		"commands": [
			{
				"command": "calicoColors.addColor",
				"category": "Calico Colors",
				"title": "Add Color"
			},
			{
				"command": "calicoColors.clearColors",
				"category": "Calico Colors",
				"title": "Clear Colors",
				"icon": "$(clear-all)"//vscode内置图标
			}
		],
		"menus": {
			"view/title": [//标题后面的图标
				{
					"command": "calicoColors.clearColors",
					"group": "navigation",
					"when": "view == calicoColors.colorsView"//控制什么时机展示,对应上面的视图id
				}
			]
		}
	},

VS Code API

vscode module

ParameterDescription
viewId: stringview的唯一id,需要匹配 contribution 里的views
provider: WebviewViewProviderwebview 视图的提供者。provider是一个类的实例,这个类需要实现WebviewViewProvider接口(resolveWebviewView方法)
	public resolveWebviewView(
		webviewView: vscode.WebviewView,
		context: vscode.WebviewViewResolveContext,
		_token: vscode.CancellationToken
	) {
		
		webviewView.webview.options = {
			// Allow scripts in the webview
			enableScripts: true,

			localResourceRoots: [this._extensionUri],//限制资源访问路径
		};
		webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);//设置webview内容
                
          webviewView.webview.postMessage({ type: 'addColor' });//extension向webview发送消息
              // 处理信息从extension到webview
                //window.addEventListener('message', event => {
                   // const message = event.data; // The json data that the extension sent
                 //   switch (message.type) {
                  //      case 'addColor':
                   //         {
                    //            addColor();
                    //            break;
                  //          }
                //    }
             //   });
          
		webviewView.webview.onDidReceiveMessage((data) => {//接受webview发送给extension的信息
			switch (data.type) {
				case 'colorSelected': {
					vscode.window.activeTextEditor?.insertSnippet(
						new vscode.SnippetString(`#${data.value}`)
					);
					break;
				}
			}
		});
                //webview里发送消息
                // const vscode = acquireVsCodeApi();
                // vscode.postMessage({ type: 'colorSelected', value: color });
	}

webview里加载本地内容

Webview 在无法直接访问本地资源的隔离上下文中运行。这样做是出于安全原因。这意味着,为了从您的扩展加载图像、样式表和其他资源,或者从用户当前工作区加载任何内容,您必须使用该Webview.asWebviewUri函数将本地 URI 转换file:为 VS Code 可以用来加载的特殊 URI本地资源的子集。

	private _getHtmlForWebview(webview: vscode.Webview) {
		// Get the local path to main script run in the webview, then convert it to a uri we can use in the webview.
		const scriptUri = webview.asWebviewUri(
			vscode.Uri.joinPath(this._extensionUri, 'media', 'main.js')//对本地js文件的处理
		);


		return `<!DOCTYPE html>
			<html lang="en">
			<head>
				<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
				<title>Cat Colors</title>
			</head>
			<body>
				<ul class="color-list">
				</ul>

				<button class="add-color-button">Add Color</button>

				<script src="${scriptUri}"></script>
			</body>
			</html>`;
	}
}

状态保存

当webview移动到后台又再次显示时,webview中的任何状态都将丢失。

在webview的js中我们可以使用vscode.getState()vscode.setState()方法来保存和恢复JSON可序列化状态对象。当webview被隐藏时,即使webview内容本身被破坏,这些状态仍然会保存。当然了,当webview被销毁时,状态将被销毁。

//初始
const oldState = vscode.getState() || { colors: [] };
	let colors = oldState.colors;
	updateColorList(colors);
        
//有更新数据就保存一下
vscode.setState({ colors: colors });