背景
WebView2 中,前端到后端的消息传递,通常是不支持传递对象的。但是我在查阅官方文档时发现了一个例外,那就是方法postMessageWithAdditionalObjects
如何传递附加对象
webview2中,前端 js 向后端传递消息通常使用 window.chrome.webview.postMessage
方法,postMessage
的定义如下:
/**
* When the page calls postMessage, the message parameter is converted to JSON and is posted
* asynchronously to the WebView2 host process. This will result in either the
* CoreWebView2.WebMessageReceived event or the CoreWebView2Frame.WebMessageReceived event being
* raised, depending on if postMessage is called from the top-level document in the WebView2
* or from a child frame. See CoreWebView2.WebMessageReceived( Win32/C++, .NET, WinRT).
* See CoreWebView2Frame.WebMessageReceived( Win32/C++, .NET, WinRT).
* @param message The message to send to the WebView2 host. This can be any object that can be
* serialized to JSON.
*/
postMessage(message: any) : void;
当我们使用postMessage
传递任何数据类型时,都将被转为 json 字符串进行传递。
postMessageWithAdditionalObjects
接受两个参数,第一个参数和postMessage
的参数一样,第二个参数允许传递一个 js 对象列表,它会被转换为原生代码中对应的类。
/**
* When the page calls `postMessageWithAdditionalObjects`, the `message` parameter is sent to WebView2 in the same
* fashion as {@link WebView.postMessage}.
* Objects passed as 'additionalObjects' are converted to their native types and will be available in the
* `CoreWebView2WebMessageReceivedEventArgs.AdditionalObjects` property.
* @param message The message to send to the WebView2 host. This can be any object that can be serialized to JSON.
* @param additionalObjects A sequence of DOM objects that have native representations in WebView2.
* This parameter needs to be ArrayLike.
*
* The following DOM types are mapped to native:
* DOM | Win32 | .NET | WinRT
* ------ | ------------------ | ------------------- | ---------------------------
* File | ICoreWebView2File | System.IO.FileInfo | Windows.Storage.StorageFile
*
* `null` or `undefined` entries will be passed as `null` type in WebView2. Otherwise if an invalid or unsupported
* object is passed via this API, an exception will be thrown and the message will fail to post.
*/
postMessageWithAdditionalObjects(message: any, additionalObjects: ArrayLike<any>): void;
使用示例
经测试,目前只支持前端的File
类型,使用示例如下:
前端:
<input id="file" type="file" value="选择文件" accept="*/*"/>
import {onMounted} from "vue";
onMounted(() => {
const file = document.querySelector("#file") as HTMLInputElement | null;
file?.addEventListener("change", () => {
console.log(file.files);
if (file.files != null) {
window.chrome.webview.postMessageWithAdditionalObjects("files", file.files);//files的类型是 FileList
}
})
})
后端接收的方法:
#region 监听前端消息
webview.CoreWebView2.WebMessageReceived += CoreWebView2OnWebMessageReceived;
#endregion
private void CoreWebView2OnWebMessageReceived(object? sender, CoreWebView2WebMessageReceivedEventArgs e)
{
var message = e.TryGetWebMessageAsString();
var objs = e.AdditionalObjects;
var a = e.Source;
Debug.WriteLine(JsonSerializer.Serialize(objs[0]));
}
当前端选择一个图片时,前端打印选择的结果:
传递给后端,后端接收到的数据:
前端从file.files
拿到的数据是没有路径的,传给后端后有了完整路径,是不是很神奇。