从本机代码调用 Web 端代码

在 WebView2 控件中使用 JavaScript 允许你自定义本机应用以满足你的需求。 本文探讨如何在 WebView2 中使用 JavaScript,并回顾如何使用高级 WebView2 特性和函数进行开发。

开始之前

本文假定你已有一个工作项目。 如果没有项目,但想继续操作,请参阅 WebView2 入门。

基本 WebView2 函数

使用以下函数在 WebView2 应用的本机代码中嵌入 JavaScript:

API 说明
ExecuteScriptAsync 在 WebView2 控件中运行 JavaScript。 在加载页面文档 对象模型 (DOM) 内容 或 完成导航后调用此方法。 请参阅 WebView2 入门。
AddScriptToExecuteOnDocumentCreatedAsync 创建 DOM 时在每一页上运行。 在初始化 CoreWebView2 后调用此方法。

方案:ExecuteScript JSON 编码结果

由于结果 ExecuteScriptAsync 是 JSON 编码的,因此,如果 JavaScript 的评估结果为字符串,则本机代码将收到 JSON 编码的字符串,而不是字符串的值。

例如,以下本机代码执行的脚本会生成一个字符串。 生成的字符串包括开头的引号、末尾的引号和转义斜杠:

string result = await coreWebView2.ExecuteScriptAsync(@"'example'");
Debug.Assert(result == "\"example\"");

该脚本返回为你进行 JSON 编码的 ExecuteScript 字符串。 如果您的 Web 端代码已经调用 JSON.stringify ,则结果将双重编码为 JSON 字符串,其值为 JSON 字符串。

只有直接出现在结果中的属性才包含在 JSON 编码对象中;继承的属性不包括在 JSON 编码对象中。 大多数 DOM 对象继承所有属性,因此 Web 端代码必须将属性的值显式复制到另一个对象中,并将该对象返回到本机代码。 例如:

Script 结果
performance.memory {}
(() => { const {totalJSHeapSize, usedJSHeapSize} = performance.memory; return {totalJSHeapSize, usedJSHeapSize}; })(); {"totalJSHeapSize":4434368,"usedJSHeapSize":2832912}

当我们返回 仅 performance.memory时,我们不会在结果中看到它的任何属性,因为所有属性都是继承的。 如果相反,Web 端代码将特定属性值从 performance.memory 复制到新对象并返回该对象,则本机代码将在结果中看到这些属性。

当通过 ExecuteScriptAsync执行脚本时,该脚本将在全局上下文中运行。 将脚本放在匿名函数中会有所帮助,这样您定义的任何变量都不会污染全局上下文。

例如:

  • 如果您多次运行该脚本 const example = 10; ,则在您随后运行该脚本时将引发异常,因为 example 在您第一次运行它时就定义了它。

  • 如果改为运行该脚本(() => { const example = 10; })();example,则变量将在该匿名函数的上下文中定义。 这样,它就不会污染全球环境,并且可以多次运行。

方案:运行专用的 JavaScript 文件

可以从 WebView2 控件访问专用 JavaScript 文件。

内联 JavaScript 代码适用于快速 JavaScript 命令。 但是,内联 JavaScript 代码不支持代码编辑器中的颜色主题和行格式。 这使得编写大量代码变得困难,例如在 Visual Studio 中编写。

若要解决此问题,请创建一个包含代码的单独 JavaScript 文件,然后使用 ExecuteScriptAsync 参数传递对该文件的引用。

若要创建和使用单独的专用 JS 文件,请执行以下操作:

  1. 在项目中创建 .js 文件,并添加要运行的 JavaScript 代码。 例如,创建一个名为 script.js的文件。

  2. 通过在页面导航完成后粘贴以下代码,将 JavaScript 文件转换为传递给 ExecuteScriptAsync的字符串:

    string text = System.IO.File.ReadAllText(@"C:\PATH_TO_YOUR_FILE\script.js");
    
  3. 将 text 变量传递给 ExecuteScriptAsync:

    await webView.CoreWebView2.ExecuteScriptAsync(text);
    

方案:删除拖放功能

在本部分中,你将使用 JavaScript 从 WebView2 控件中删除拖放功能。

首先,浏览当前的拖放功能:

  1. 创建 .txt 文件以便进行拖放。 例如,创建一个名为 contoso.txt 的文件并向其添加文本。

  2. 按 F5 生成并运行项目。

  3. 将文件拖放 contoso.txt 到 WebView2 控件中。 此时将打开一个新窗口,这是示例项目中代码的结果:

    拖放 contoso.txt的结果

  4. 接下来,添加代码以从 WebView2 控件中删除拖放功能。 在代码中初始化 CoreWebView2 对象后,粘贴以下代码:

    await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(
       "window.addEventListener('dragover',function(e){e.preventDefault();},false);" +
       "window.addEventListener('drop',function(e){" +
          "e.preventDefault();" +
          "console.log(e.dataTransfer);" +
          "console.log(e.dataTransfer.files[0])" +
       "}, false);");
    
  5. 按 F5 生成并运行项目。

  6. 尝试拖放 contoso.txt 到 WebView2 控件中。 确认无法拖放。

方案:删除上下文菜单

在本部分中,从 WebView2 控件中删除右键单击菜单。

首先,浏览右键单击菜单的当前功能:

  1. 按 F5 生成并运行项目。

  2. 右键单击 WebView2 控件上的任意位置。 上下文菜单显示默认右键单击菜单命令:

    显示默认命令的右键单击菜单

    接下来,添加代码以从 WebView2 控件中删除右键单击菜单功能。

  3. 在代码中初始化 CoreWebView2 对象后,粘贴以下代码:

    await webView.CoreWebView2.ExecuteScriptAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
    
  4. 按 F5 生成并运行项目。 确认无法打开右键单击菜单。

另请参阅