当前位置: 首页 > news >正文

vscode插件开发之 - 消息通信

  在开发vscode插件过程中,有一个典型场景是webview与extension.ts进行通信,例如,webview上的某些信息发送改变时,需要发送消息传递给extension.ts. 如果使用react框架构建vscode插件的webview,如何实现webview与extension.ts之间通信呢?如果要实现信息通信,需要三个步骤:

  步骤一:在react的src目录下,定义一个全局变量vscode,代码如下所示:这里定义了Message数据结构,定义了VSCode别名。

interface Message {command: string;content: string;[key: string]: any;
}
type VSCode = {Uri: any;env: any;postMessage(message: Message): void;getState(): any;setState(state: any): void;
};declare const vscode: VSCode;

   步骤二:在react的source code下面,在需要发送共享消息的地方,调用vscode.postMessage()发送消息。示例代码如下所示,当input中的信息或者dropdown中的信息发生改变时,就会通过postMessage发送消息出去。

const App = () => {const [sex, setSex] = useState('');const handleChange = (event: any) => {setSex(event.target.value);vscode.postMessage({ command: "sexChange", content: event.target.value });};const handleNameChange = (event: any) => {const value = event.target.value;vscode.postMessage({ command: "nameChange", content: value });}const handelAgeChange = (event: any) => {const value = event.target.value;vscode.postMessage({ command: "ageChange", content: value });}return (<div><div><input type="text" name="name" onChange={handleNameChange}></input></div><div><input type="text" name="age" onChange={handelAgeChange}></input></div><div><select value={sex} onChange={handleChange} ><option>girl</option><option>boy</option></select></div><div><button>ShowIt</button></div></div>);
};
const rootElement = document.getElementById('root');
if (rootElement) {const root = (ReactDOM as any).createRoot(rootElement);root.render(<App />);
} else {console.error('Root element not found!');
}

  步骤三:在extension.ts代码中,增加监听消息的代码,如果是多个信息需要汇聚,那么可以定义个公共的数据对象,直接更新这个对象即可。调用webview.onDidReceiveMessage监听消息,并将接受到的内容,更新到info这个变量上。

        webviewView.webview.onDidReceiveMessage((message: any) => {if (message.command === "nameChange") {info.name = message.content} else if (message.command === "ageChange") {info.age = message.content} else if (message.command === "sexChange") {info.sex = message.content}})
export interface Info {name: string,age: number,sex: string
}export let info: Info = {name: "",age: 0,sex: "boy"
}

  修改完上述代码后,就可以进行验证,是否能在extension.ts上接受不了webview上的输入信息了,这里当trigger demo.showOne command的时候,在message上,打印了info这个对象。

    context.subscriptions.push(vscode.commands.registerCommand('demo.showOne', () => {vscode.window.showInformationMessage('I am showOne.');vscode.window.showInformationMessage(JSON.stringify(info))}));

   重新编译后,在extension的webview上输入一些信息,在点击右键菜单的showOne,在右下角的message上成功打印出了消息,说明消息传递成功。

  那么,为什么在webview的source code上定义了Message和VSCode对象后,就能调用postMessage发送消息呢?实际上如果要成功发送消息,在extension.ts的webview.html代码中还需要添加上“const vscode = acquireVsCodeApi()”才行。

    private getWebviewContent(webviewUri: vscode.Uri): string {return `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Taoli Webview</title></head><body><div id="root"></div><script>const vscode = acquireVsCodeApi();</script><script src="${webviewUri}"></script></body></html>`;}
}

消息通信工作原理

   在 VS Code 扩展中,webview 是一个内嵌的 HTML 环境,类似于一个 iframe。acquireVsCodeApi 函数是 VS Code 提供的一个全局函数,允许 webview 内部的 JavaScript 代码获取一个 VS Code API 对象,从而与扩展主进程进行通信。调用该函数会返回一个包含一组方法的对象,这些方法用于与扩展主进程进行双向通信。主要的方法包括:
postMessage(message: any): void
getState(): any
setState(state: any): void

   在步骤一中定义的VScode和Message对象,这些代码是告诉 TypeScript 编译器,在运行时将会有一个全局的 vscode 对象,该对象符合 VSCode 类型。这是为了让 TypeScript 知道 vscode 对象的存在,并进行类型检查和自动补全。实际当webview运行的时候,使用的是acquireVsCodeApi 函数返回的VScode常量。这个常量提供的方法和之前定义的一致。通过这种方式实现了消息通信。

1.发送消息:webview 内部的代码使用 vscode.postMessage 方法发送消息到主进程。
2.接收消息:主进程使用 webview.onDidReceiveMessage 方法接收并处理这些消息。
3.双向通信:如果需要,主进程还可以使用 webview.postMessage 方法向 webview 发送消息,从而实现双向通信。

相关文章:

  • Apache HttpClient总览
  • QSS/QFrame/connect/两个窗口界面的连接/窗口的优化
  • DoIP——step2:车辆发现
  • 内网穿透的原理:实现远程访问的技术揭秘
  • Aeron:两个代理之间的单向IPC(One-way IPC between two agents)
  • visual studio下载安装
  • 【MySQL基础随缘更系列】AB复制
  • 你是否感受到AI就在身边?
  • Leetcode - 132双周赛
  • 海康充电桩报文校验TCP校验和
  • 刷题——链表中倒数最后k个结点
  • 什么是隐马尔可夫模型?
  • 【第5章】Stable Diffusion大模型(简介/两种版本/安装/模型推荐/使用方式)ComfyUI基础入门教程
  • 【Vue3】使用v-model实现父子组件通信(常用在组件封装规范中)
  • Part 4.2 背包动态规划
  • android 一些 utils
  • Apache Spark Streaming 使用实例
  • docker python 配置
  • eclipse(luna)创建web工程
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • EventListener原理
  • JSDuck 与 AngularJS 融合技巧
  • Linux Process Manage
  • Lsb图片隐写
  • SegmentFault 2015 Top Rank
  • 多线程 start 和 run 方法到底有什么区别?
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 实战|智能家居行业移动应用性能分析
  • 使用 QuickBI 搭建酷炫可视化分析
  • 使用Gradle第一次构建Java程序
  • gunicorn工作原理
  • #162 (Div. 2)
  • #pragma once
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (C++)八皇后问题
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (过滤器)Filter和(监听器)listener
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)socket Aio demo
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .NET下的多线程编程—1-线程机制概述
  • @modelattribute注解用postman测试怎么传参_接口测试之问题挖掘
  • @RequestMapping-占位符映射
  • @Transactional 竟也能解决分布式事务?
  • @Transactional类内部访问失效原因详解
  • [ 网络通信基础 ]——网络的传输介质(双绞线,光纤,标准,线序)
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择