在 WebView2 应用中使用帧

框架允许你将其他网页嵌入到自己的网页中。 框架是网页中的子页面或区域,类似于网页中的网页。

iframe 是一种类型的帧。 其他类型的帧包括 frameset、、portalembedfencedFrameobject。 帧main WebView2 类型为 CoreWebView2Frame,当前为顶级 iframe 启用。 计划支持其他类型的帧。

WebView2 支持与 iframe 交互的 API。 可以执行下列操作:

  • 了解何时创建 iframe。
  • 了解 iframe 何时导航到其他 URL。 这与 WebView2 应用的状态机导航事件相同。
  • 在主机应用和 iframe 之间进行通信,双向发送消息。
  • 允许应用忽略 X-Frame-Options HTTP 响应标头。

另请参阅:

订阅 FrameCreated 事件以获取帧

若要与主机应用中的帧交互,第一步是订阅 FrameCreated 事件,以便主机应用获取帧对象。 每当创建新帧时,将 FrameCreated 引发该事件。 主机应用获取帧对象后,使用帧对象监视更改并与此特定帧交互。

主机应用必须通过订阅事件来 CoreWebView2Frame.Destroyed 监视帧的生存期,因为当帧被销毁时,主机应用无法再引用该帧。 在每个新网页导航期间,都会创建和销毁帧。 CoreWebView2Frame.IsDestroyed使用 方法检查帧是否仍然存在。

另请参阅:

  • WebView2 功能和 API 概述中的 iframe

创建框架后,框架将导航到框架的源 URL。 iframe 使用导航和导航事件,例如 FrameNavigationStartingNavigationCompleted。 当框架导航到源 URL 时,将引发以下导航事件:

  • NavigationStarting
  • ContentLoading
  • HistoryChanged
  • DOMContentLoaded
  • NavigationCompleted

在框架内导航的频率

导航可能会在框架中发生。 作为一个简单的用例, iframe 元素的 source 属性是一个 URL(如 wikipedia.com),该 URL 加载到 iframe 中。 通常,导航会在创建框架后立即发生。 ContentLoading然后引发 、 DOMContentLoadedNavigationCompleted 事件。

框架本身正在导航。 网页导航到 URL。 同样,帧可能会导航。

创建框架后,框架将按照主机应用的驱动方式进行导航。 若要监视main页中发生的情况,事件(如 NavigationStartingNavigationCompleted),并使HistoryChanged主机应用能够在框架或网页之间来回导航。 框架导航到新 URL 的频率低于网页,但支持相同的导航样式。 用户通常无法在框架内导航,尽管 JavaScript 支持该操作:框架在导航方面通常是静态的。

另请参阅:

导航事件:

对于重复的等效 NavigationStarting 项和 NavigationCompleted 事件,建议使用 上的 CoreWebView2Frame 事件,而不是上的 CoreWebView2等效的取代事件,因为 类型 CoreWebView2Frame 支持更多方案,以允许与帧交互。

另请参阅:

在 iframe 中使用主机对象

若要在主机应用的本机端与 iframe 中的 JavaScript 之间进行通信,请使用主机对象。 主机对象是在主机应用中创建的对象,然后从应用的网页端的 JavaScript 代码使用。

通过主机对象从框架中的脚本使用本机端 API 类似于从 Web 端代码调用本机端代码中所述的 Web/本机互操作页面结构:

若要在 iframe 中使用主机对象,请执行以下操作:

  1. 定义主机对象并实现 IDispatch
  2. 使用 AddHostObjectToScriptWithOrigins (Win32) 或 AddHostObjectToScript (.NET) 在本机端添加主机对象。
  3. 在 Web 端代码中的 JavaScript 中,使用 chrome.webview.hostObjects.<name> API 访问此主机对象。

若要从框架中的 Web 端 JavaScript 访问和控制本机端对象,请使用 AddHostObjectToScriptWithOrigins (Win32) 或 CoreWebView2Frame.AddHostObjectToScript (.NET) ,其中包含 参数 origins 。 参数 origins 指定出于安全原因,允许 iframe 访问哪些 URL。 此参数标识 iframe 将有权访问主机对象的 URL。

如果框架导航到不在 origins 列表中的 URL,则帧将无法操作宿主对象;该帧将无法读取或写入任何属性。 请参阅框架 方法AddHostObjectToScript 的方法名称表。 请参阅以下两行:

  • applyHostFunctiongetHostPropertysetHostProperty
  • getLocalPropertysetLocalProperty

上述方法的工作方式类似于以下方法:

示例代码

请参阅从 Web 端代码调用本机代码中的步骤 6:调用 AddHostObjectToScript 以将主机对象传递到Web 端代码

另请参阅:

发送和接收消息

可以在本机应用与 iframe 中的 JavaScript 代码之间发送消息:

  • 可以将消息从 HTML 页的 iframe 中的 JavaScript 发送到主机应用。
  • 可以将消息从主机应用发送到 HTML 页的 iframe 中的 JavaScript。

将 Web 消息从 iframe 发送到主机应用

若要将 Web 消息从 iframe 发送到主机应用,请使用 window.chrome.webview.postMessage 方法:

window.chrome.webview.postMessage(`SetTitleText ${titleText.value}`);

若要在主机应用中接收这些消息,主机应用必须订阅 WebMessageReceived event

将消息从主机应用发送到 iframe

主机应用通过调用 PostWebMessageAsJsonPostWebMessageAsString 方法将消息发送到 iframe。

iframe 通过订阅 window.chrome.webview.addEventListener('message') 事件来接收消息,如下所示:

window.chrome.webview.addEventListener('message', arg => {
    // implement event listener here
});

另请参阅:

使用 ExecuteScript 在 iframe 中运行 JavaScript 代码

WebView2 应用可以使用 在框架 ExecuteScript中运行任何 JavaScript。

若要在 iframe 中运行脚本,必须创建执行上下文。 执行上下文是在事件之后 ContentLoading 创建的,因此,如果在 ExecuteScript 引发事件之前 ContentLoading 调用 ,脚本将不会运行,并且将返回字符串 null

有关事件的信息 ContentLoading ,请参阅 WebView2 应用的导航事件,该事件对框架和网页有效。

另请参阅:

使用 WebResourceRequested iframe 中的 事件修改网络事件

此功能是实验性的

对于 iframe,可以使用 事件侦听网络事件并对其进行 WebResourceRequested 修改。

另请参阅:

请参阅最新的预发行版 API。 以下链接包含 1.0.1466-prerelease。 在 API 参考文档左上角的 “版本 ”下拉列表中,选择最新的预发行版。

忽略 X-Frame-Options 以在框架内呈现网页

X-Frame-Options网页使用 HTTP 响应标头来防止应用程序在框架内呈现该网页。 属性 AdditionalAllowedFrameAncestors 允许应用程序绕过 X-Frame-Options 标头,在框架内呈现网页。

另请参阅:

在主机应用中使用 iframe 的示例

此示例代码演示如何使用帧 API,包括:

  • FrameCreated
    • CoreWebView2FrameCreatedEventArgs
  • DOMContentLoaded
    • CoreWebView2DOMContentLoadedEventArgs
  • ExecuteScript

此示例代码从 WebView2WpfBrowser 示例中的 MainWindow.xaml.cs精简。

        void DOMContentLoadedCmdExecuted(object target, ExecutedRoutedEventArgs e)
        {
            // Subscribe to the FrameCreated event to obtain the frame object when 
            // it's created.
            webView.CoreWebView2.FrameCreated += WebView_FrameCreatedDOMContentLoaded;
            webView.NavigateToString(@"<!DOCTYPE html>" +
                                      "<h1>DOMContentLoaded sample page</h1>" +
                                      "<h2>The content to the iframe and below will be added after DOM content is loaded </h2>" +
                                      "<iframe style='height: 200px; width: 100%;'/>");
        }

        void WebView_FrameCreatedDOMContentLoaded(object sender, CoreWebView2FrameCreatedEventArgs args)
        {
            // In order for ExecuteScriptAsync to successfully run inside the iframe, 
            // subscribe to the ContentLoading or DOMContentLoaded event.  Once these 
            // events are raised, you can call ExecuteScriptAsync.
            args.Frame.DOMContentLoaded += (frameSender, DOMContentLoadedArgs) =>
            {
                args.Frame.ExecuteScriptAsync(
                    "let content = document.createElement(\"h2\");" +
                    "content.style.color = 'blue';" +
                    "content.textContent = \"This text was added to the iframe by the host app\";" +
                    "document.body.appendChild(content);");
            };
        }

API 参考概述

WebView2 功能和 API 概述中列出的以下功能包括与帧相关的 API:

另请参阅

外部页面: