信息提示与交互
插件与用户交互最直接的方式就是弹窗提示与对话框。VS Code 提供一整套 window.show* API,从简单消息到输入框、选择列表、文件对话框,覆盖绝大多数交互场景。
消息提示三兄弟
window.showInformationMessage / showWarningMessage / showErrorMessage 是最常用的消息提示,按严重程度区分:
| API | 视觉风格 | 适用场景 |
|---|---|---|
showInformationMessage | 蓝色信息 | 提示、成功反馈 |
showWarningMessage | 黄色警告 | 需要提醒用户注意 |
showErrorMessage | 红色错误 | 操作失败、异常 |
typescript
import * as vscode from 'vscode';
// 信息
vscode.window.showInformationMessage('操作成功');
// 警告
vscode.window.showWarningMessage('该操作不可撤销');
// 错误
vscode.window.showErrorMessage('文件保存失败');带按钮的消息
三个 API 都支持附加操作按钮,点击后返回按钮文本:
typescript
const choice = await vscode.window.showInformationMessage(
'是否保存更改?',
{ modal: true }, // 模态对话框(可选)
'保存', // 按钮 1
'不保存', // 按钮 2
'取消' // 按钮 3
);
if (choice === '保存') {
// 执行保存
} else if (choice === '不保存') {
// 放弃保存
}模态 vs 非模态
| 类型 | 配置 | 特点 |
|---|---|---|
| 非模态 | 默认 | 右下角 Toast,不阻塞操作 |
| 模态 | { modal: true } | 居中弹窗,必须处理后才可继续 |
模态对话框最多支持 3 个按钮(移动端 2 个)。
输入框 showInputBox
需要用户输入文本时使用 window.showInputBox:
typescript
const name = await vscode.window.showInputBox({
title: '输入项目名称',
prompt: '请输入新项目名称', // 输入框上方的说明
placeHolder: 'my-project', // 输入占位提示
value: 'default-name', // 初始值
validateInput: (text) => {
// 输入校验:返回 undefined 通过,返回字符串为错误提示
if (text.length < 3) {
return '名称至少 3 个字符';
}
if (text.includes(' ')) {
return '名称不能包含空格';
}
return undefined;
},
ignoreFocusOut: true // 焦点移出时不自动关闭
});
if (name) {
vscode.window.showInformationMessage(`项目名称: ${name}`);
}| 选项 | 作用 |
|---|---|
title | 输入框窗口标题 |
prompt | 输入框上方说明文字 |
placeHolder | 未输入时的灰色占位 |
value | 预填默认值 |
validateInput | 实时校验函数 |
ignoreFocusOut | 点击外部时不关闭 |
用户取消时返回 undefined,务必判空。
快速选择 showQuickPick
需要从列表中选择时使用 window.showQuickPick,比对话框更高效:
typescript
const items = [
{ label: '$(file-code) TypeScript', description: '语言类型', detail: '用于编写插件' },
{ label: '$(file) JavaScript', description: '轻量选择' },
{ label: '$(gear) Other' }
];
const picked = await vscode.window.showQuickPick(items, {
title: '选择语言',
placeHolder: '选择一种语言',
canPickMany: false, // 是否多选
ignoreFocusOut: true,
matchOnDescription: true, // 允许按描述匹配
matchOnDetail: true // 允许按详情匹配
});
if (picked) {
vscode.window.showInformationMessage(`选择了 ${picked.label}`);
}QuickPickItem 结构
| 字段 | 作用 |
|---|---|
label | 显示文本(支持 $(图标ID) 语法) |
description | 次要描述(灰色) |
detail | 详细信息(第二行) |
picked | 预选状态 |
alwaysShow | 始终显示(默认在输入后仍过滤) |
多选模式
typescript
const picked = await vscode.window.showQuickPick(items, {
canPickMany: true
});
// picked 为数组,可能为空数组
if (picked && picked.length > 0) {
const names = picked.map(item => item.label).join(', ');
vscode.window.showInformationMessage(`选中: ${names}`);
}文件对话框 showOpenDialog / showSaveDialog
选择或保存文件使用文件对话框:
typescript
// 打开对话框
const uris = await vscode.window.showOpenDialog({
title: '选择文件',
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
defaultUri: vscode.Uri.file('C:\\'),
openLabel: '选择',
filters: {
'图片文件': ['png', 'jpg', 'gif'],
'所有文件': ['*']
}
});
if (uris && uris.length > 0) {
const uri = uris[0];
vscode.window.showInformationMessage(`选择: ${uri.fsPath}`);
}typescript
// 保存对话框
const uri = await vscode.window.showSaveDialog({
title: '保存导出结果',
defaultUri: vscode.Uri.file('export.txt'),
filters: {
'文本文件': ['txt', 'md']
}
});
if (uri) {
await vscode.workspace.fs.writeFile(
uri,
Buffer.from('导出内容', 'utf8')
);
}| 选项 | 作用 |
|---|---|
canSelectFiles/Folders | 允许选择的类型 |
canSelectMany | 是否多选 |
defaultUri | 默认路径 |
openLabel | 确认按钮文案 |
filters | 文件类型过滤 |
完整示例:交互组合
把输入框、快速选择、文件对话框串成一个完整交互流程:
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('interact.createFile', async () => {
// 1. 选择文件类型
const type = await vscode.window.showQuickPick(
[
{ label: '$(file-code) TypeScript', value: '.ts' },
{ label: '$(file) JavaScript', value: '.js' },
{ label: '$(file-text) Markdown', value: '.md' }
],
{ title: '选择文件类型' }
);
if (!type) {
return;
}
// 2. 输入文件名
const name = await vscode.window.showInputBox({
title: '输入文件名',
placeHolder: 'my-file',
validateInput: (text) =>
text.trim() ? undefined : '文件名不能为空'
});
if (!name) {
return;
}
// 3. 选择保存位置
const uri = await vscode.window.showSaveDialog({
defaultUri: vscode.Uri.file(`${name}${type.value}`)
});
if (!uri) {
return;
}
// 4. 写入文件
await vscode.workspace.fs.writeFile(uri, new Uint8Array());
vscode.window.showInformationMessage(`已创建 ${uri.fsPath}`);
})
);
}常见问题
| 问题 | 处理 |
|---|---|
| 用户取消后报错 | 所有对话框返回 undefined,使用前判空 |
| 消息按钮不显示 | 模态对话框最多 3 个按钮 |
| 中文乱码 | 写入文件时明确指定 utf8 |
| 输入框关闭太快 | 设置 ignoreFocusOut: true |
信息提示与交互 API 是插件与用户沟通的桥梁,掌握后可以构建流畅的操作反馈与参数输入流程。