首页
/ Electron `<webview>` 标签完整指南:内嵌外部页面、属性配置与 API 事件全解析

Electron `<webview>` 标签完整指南:内嵌外部页面、属性配置与 API 事件全解析

2026-09-06 18:22:51作者:明树来

本文基于 Electron 官方仓库中的 docs/api/webview-tag.md 完整整理并辅以源码佐证。<webview> 是 Electron 中用于在应用内隔离地展示外部 Web 内容的标签:它像 <iframe> 一样嵌入页面,却运行在独立进程与独立 frame 中。读完本文,你将掌握如何启用 <webview>、理解其 OOPIF 内部实现与安全模型、熟练配置全部 14 个标签属性、调用其 60+ 方法与 40+ 个 DOM 事件,并了解其局限性与替代方案(iframeWebContentsView)。

⚠️ 使用警告:官方不推荐优先使用 <webview>

Electron 的 webview 标签基于 Chromium 的 webview,而 Chromium 侧正在经历剧烈的架构变迁,这会影响 webview 的稳定性,包括渲染、导航与事件路由等方面。官方当前建议不要使用 webview 标签,优先考虑以下替代方案:

  • 普通 <iframe>
  • WebContentsView
  • 一种完全避免嵌入内容的整体架构。

若你评估后仍需要 webview 的能力(例如需要隔离的独立进程、自定义协议或与 Chromium webview 语义兼容的存量应用),再继续阅读本文。

启用 <webview> 标签

webview 标签在 Electron >= 5 中默认关闭。你需要在使用 BrowserWindow 构造窗口时设置 webPreferences.webviewTagtrue

const { BrowserWindow } = require('electron')

const win = new BrowserWindow({
  webPreferences: {
    webviewTag: true // 显式开启 <webview>
  }
})

从源码看,该选项的默认值是 falselib/browser/guest-window-manager.ts 中创建 guest 窗口时 webviewTag: false;而主进程侧在 shell/browser/web_contents_preferences.cc 会通过 web_preferences.Get(options::kWebviewTag, &webview_tag_) 读取该开关,并在渲染进程偏好中下发。

渲染进程是否真正注册 <webview> 自定义元素,由 lib/renderer/common-init.ts 读取 webviewTag 后调用 webViewInit 决定:

  • 只有 webviewTag === true 且当前页面本身不是 webview guest 时,才会执行注册逻辑——这一检查来自 lib/renderer/web-view/web-view-init.ts,其注释明确说明 "Don't allow recursive <webview>",即禁止在 webview 内再嵌套 webview
  • 当页面启用了 contextIsolation 时,guestViewInternal 桥接对象通过 v8Util.setHiddenValue 存放在 window 隐藏属性中,由隔离世界的初始化代码 lib/isolated_renderer/init.ts 调用同一套 setupWebView 完成注册。

注册动作本身发生在 lib/renderer/web-view/web-view-element.ts:在允许的特殊作用域内调用 window.customElements.define('webview', WebViewElement),同时暴露 window.WebView,并删除 connectedCallback / disconnectedCallback / observedAttributes 等生命周期钩子,防止开发者自行调用产生未预期行为。

概览:隔离进程中的“客座内容”

在一个隔离的 frame 与进程中显示外部 Web 内容。

  • 进程:Renderer(渲染进程)
  • 该类'electron' 模块导出,只能作为 DOM 上 <webview> 元素实例使用。

webview 用于把"访客"内容(guest content,例如其他网页)嵌入到 Electron 应用中。guest 内容被限制在 webview 容器内部;应用内的嵌入页(embedder page)控制 guest 内容的布局与渲染方式。

<iframe> 的关键区别在于:

  • <webview> 与应用运行在不同的进程中
  • 不拥有你的网页同样的权限;
  • 应用与嵌入内容之间的所有交互都是异步的。

这使你的应用免于被嵌入内容攻击。

[!NOTE] 大多数从宿主页面调用到 webview 上的方法,都需要同步调用到主进程。具体来说,宿主页面方法经由 guestViewInternal.invokeSync(...)(同步方法)或 invoke(...)(异步方法)走 IPC 到达主进程侧的 guest 管理器执行,见 lib/renderer/web-view/web-view-impl.ts

最小示例

在最简单的形式里,webview 标签包含目标网页的 src 以及控制容器外观的 CSS:

<webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>

若希望以任何方式控制 guest 内容,可以编写 JavaScript 监听 webview 事件并通过方法响应。下面的例子注册了两个事件监听器:一个监听页面开始加载、一个监听页面停止加载,加载期间显示 "loading..." 提示:

<script>
  onload = () => {
    const webview = document.querySelector('webview')
    const indicator = document.querySelector('.indicator')

    const loadstart = () => {
      indicator.innerText = 'loading...'
    }

    const loadstop = () => {
      indicator.innerText = ''
    }

    webview.addEventListener('did-start-loading', loadstart)
    webview.addEventListener('did-stop-loading', loadstop)
  }
</script>

内部实现:基于 OOPIF 与 Shadow DOM

在底层,webview 基于 Out-of-Process iframes (OOPIF) 实现。webview 标签本质上是一个自定义元素(custom element),它使用 Shadow DOM 在内部包裹一个 <iframe> 元素。

仓库的渲染层源码完整印证了这一描述。查看 lib/renderer/web-view/web-view-element.tsWebViewElement extends HTMLElementobservedAttributes 中列出全部可观测属性;而 lib/renderer/web-view/web-view-impl.ts 的构造函数里:

const shadowRoot = this.webviewNode.attachShadow({ mode: 'open' });
const style = shadowRoot.ownerDocument.createElement('style');
style.textContent = ':host { display: flex; }';
shadowRoot.appendChild(style);
...
const iframeElement = document.createElement('iframe');
iframeElement.style.flex = '1 1 auto';
iframeElement.style.width = '100%';
iframeElement.style.border = '0';

可见 <webview> 正是"自定义元素 + open shadow root + 内部 iframe"的组合,并设置了 :host { display: flex; } 样式。此外每个 WebViewImpl 会通过 hooks.setIsWebView(iframeElement)(见 lib/renderer/web-view/web-view-init.ts)把内部 iframe 标记为 webview frame,Chromium 侧 RendererClientBase::IsWebViewFrame 据此识别,从而把该 frame 交给独立的 guest 进程处理。

因此,webview 的行为与跨域 iframe 非常相似,例如:

  • 点击进入 webview 时,页面焦点会从嵌入者 frame 移入 webview
  • 不能为 webview 添加键盘、鼠标与滚轮事件监听器(这些输入直接作用于其内部渲染进程);
  • 嵌入者 frame 与 webview 之间的所有交互都是异步的。

CSS 样式注意

请勿覆盖 <webview> 标签内部的 display:flex; 默认样式(除非按文档示例使用 display:inline-flex; 做行内布局)。该内部样式用于保证子 iframe 在传统布局与 flexbox 布局下都能撑满 webview 容器的全部宽高

标签属性(Tag Attributes)

<webview> 支持以下属性。综合 lib/renderer/web-view/web-view-constants.tslib/renderer/web-view/web-view-element.ts 可确认,被 MutationObserver 观测并参与建 guest 参数的属性恰为以下 14 个;boolean 类型属性"存在即 true"(详见 lib/renderer/web-view/web-view-attributes.tsBooleanAttributehasAttribute 取值逻辑)。

src

<webview src="https://www.github.com/"></webview>

类型 string,表示当前可见 URL。向该属性写入值会触发顶层导航;给 src 赋与当前相同的值会重新加载当前页面。src 也接受 data URL,例如 data:text/plain,Hello, world!。属性变更由 SrcAttributelib/renderer/web-view/web-view-attributes.ts)处理,读取时会基于 location.href 解析为绝对 URL。

nodeintegration

<webview src="https://www.google.com/" nodeintegration></webview>

类型 boolean。存在时 guest 页面会启用 Node 集成,可以使用 requireprocess 等 Node API 访问底层系统资源。guest 页面默认关闭 Node 集成。出于安全考虑,务必仅在受信任内容上开启。

nodeintegrationinsubframes

<webview src="https://www.google.com/" nodeintegrationinsubframes></webview>

类型 boolean,实验性选项,用于在 webview 内部的子 frame(如其中嵌套的 iframe)启用 NodeJS 支持。启用后,你的 preload 脚本会在每个 iframe 中加载,可在脚本中用 process.isMainFrame 判断当前是否为主 frame。guest 页面默认关闭。

plugins

<webview src="https://www.github.com/" plugins></webview>

类型 boolean。存在时 guest 页面可以使用浏览器插件(plugin)。插件默认禁用。

preload

<!-- 从普通文件加载 -->
<webview src="https://www.github.com/" preload="./test.js"></webview>
<!-- 或从 asar 归档加载 -->
<webview src="https://www.github.com/" preload="./app.asar/test.js"></webview>

类型 string,指定在 guest 页面其他脚本运行前加载的脚本。脚本 URL 的协议必须是 file:(即便使用 asar: 归档),因为它在底层由 Node 的 require 加载,而 require 会把 asar: 归档当作虚拟目录处理。

当 guest 页面没有启用 node 集成时,该脚本仍能访问全部 Node API,但在脚本执行结束后,Node 注入的全局对象会被删除。

httpreferrer

<webview src="https://www.github.com/" httpreferrer="https://example.com/"></webview>

类型 string,为 guest 页面设置 referrer URL。

useragent

<webview src="https://www.github.com/" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"></webview>

类型 string,在页面导航之前设置 guest 页面的 user agent。页面加载完成后如需修改,应改用 setUserAgent 方法。

disablewebsecurity

<webview src="https://www.github.com/" disablewebsecurity></webview>

类型 boolean。存在时 guest 页面将关闭 Web 安全(跨域限制等);Web 安全默认开启。该值只能在第一次导航前修改。

partition

<webview src="https://github.com" partition="persist:github"></webview>
<webview src="https://electronjs.org" partition="electron"></webview>

类型 string,设置页面使用的 session(会话)。

  • partitionpersist: 开头,页面使用持久化 session,应用内所有相同 partition 的页面共享该会话;
  • 若无 persist: 前缀,页面使用内存 session
  • 为多个页面分配相同 partition,它们即可共享同一会话;
  • 未设置 partition 时使用应用默认 session。

由于活动渲染进程的 session 无法更改,该值只能在第一次导航前修改;之后再次修改会抛出 DOM 异常。这一约束同样体现在渲染层:lib/renderer/web-view/web-view-attributes.tsPartitionAttribute.handleMutation 会检查 beforeFirstNavigation,一旦已经导航过就会打印错误并回滚旧值;而 partition="persist:"(空名)会被判定为非法。

allowpopups

<webview src="https://www.github.com/" allowpopups></webview>

类型 boolean。存在时 guest 页面被允许打开新窗口。弹窗默认禁用

webpreferences

<webview src="https://github.com" webpreferences="allowRunningInsecureContent, javascript=no"></webview>

类型 string,逗号分隔的字符串列表,用于设置在 webview 上的 web 偏好。完整支持列表见 BrowserWindow 构造选项

该字符串与 window.open 的 features 字符串采用相同格式

  • 单独出现的名字按布尔值 true 处理;
  • 通过 = 加值可为偏好指定其他值,如 javascript=no
  • 特殊值 yes1 解释为 trueno0 解释为 false

仓库中负责解析的是 lib/browser/parse-features-string.tsparseCommaSeparatedKeyValue / parseWebViewWebPreferences),其 coerce 函数正是按照上述规则把 true/1/yes 归并为 truefalse/0/no 归并为 false

安全关键偏好不能把 guest 变得比其 embedder 更不安全:当 embedder 在 contextIsolationjavascriptnodeIntegrationnodeIntegrationInWorkersandboxnodeIntegrationInSubFramesenableWebSQL 中的任一设置为更安全的值时,guest 会继承该安全值,对应 webpreferences 项会被忽略。

enableblinkfeatures

<webview src="https://www.github.com/" enableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>

类型 string,逗号分隔的字符串列表,指定启用的 Blink 特性。完整支持列表见 RuntimeEnabledFeatures.json5(Chromium 源文件)。

disableblinkfeatures

<webview src="https://www.github.com/" disableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>

类型 string,逗号分隔的字符串列表,指定禁用的 Blink 特性。支持列表同上。

方法(Methods)

<webview> 元素暴露以下方法。方法调用前 webview 元素必须已经加载完成(通常先等待 dom-ready 事件)。

示例

const webview = document.querySelector('webview')
webview.addEventListener('dom-ready', () => {
  webview.openDevTools()
})

从源码角度,宿主页面可调用的方法被分成了"同步方法"与"异步方法"两组(见 lib/common/web-view-methods.ts),在 lib/renderer/web-view/web-view-impl.ts 中通过 guestViewInternal.invokeSync(...) / invoke(...) 统一转发到主进程。此外还有一组可通过属性读写访问的 propertiesaudioMuteduserAgentzoomLevelzoomFactorzoomModeframeRate)。同步方法包括:

getURLgetTitleisLoadingisLoadingMainFrameisWaitingForResponsestopreloadreloadIgnoringCacheisCrashedsetUserAgentgetUserAgentopenDevToolscloseDevToolsisDevToolsOpenedisDevToolsFocusedinspectElementsetAudioMutedisAudioMutedisCurrentlyAudibleundoredocutcopycenterSelectionpastepasteAndMatchStyledeleteselectAllunselectscrollToTopscrollToBottomadjustSelectionreplacereplaceMisspellingfindInPagestopFindInPagedownloadURLinspectSharedWorkerinspectServiceWorkershowDefinitionForSelectiongetZoomFactorgetZoomLevelsetZoomFactorsetZoomLevel,以及导航历史组 canGoBackcanGoForwardcanGoToOffsetclearHistorygoBackgoForwardgoToIndexgoToOffset

异步方法包括:

capturePageloadURLexecuteJavaScriptinsertCSSinsertTextremoveInsertedCSSsendsendToFramesendInputEventsetLayoutZoomLevelLimitssetVisualZoomLevelLimitsprintprintToPDF

下文按用途分组给出完整签名与语义。

导航与页面加载

<webview>.loadURL(url[, options])

  • url URL
  • options Object(可选)
    • httpReferrer (string | Referrer)(可选)— HTTP Referrer URL
    • userAgent string(可选)— 发起请求的 user agent
    • extraHeaders string(可选)— 以 "\n" 分隔的额外请求头
    • postData (UploadRawData | UploadFile)[](可选)
    • baseURLForDataURL string(可选)— 供 data URL 加载其他文件时使用的 base url(需带尾部路径分隔符);仅在 url 是 data URL 且需加载其他文件时需要

返回 Promise<void> — 页面加载完成(见 did-finish-load 事件)时 resolve,加载失败(见 did-fail-load 事件)时 reject。在 webview 中加载 urlurl 必须包含协议前缀,如 http://file://

<webview>.downloadURL(url[, options])

  • url string
  • options Object(可选)
    • headers Record<string, string>(可选)— HTTP 请求头

在不发生导航的情况下发起对 url 资源的下载。

页面状态查询

  • <webview>.getURL() 返回 string — guest 页面的 URL。
  • <webview>.getTitle() 返回 string — guest 页面的标题。
  • <webview>.isLoading() 返回 boolean — guest 页面是否仍在加载资源。
  • <webview>.isLoadingMainFrame() 返回 boolean — 主 frame(而不只是其中的 iframe 等子 frame)是否仍在加载。
  • <webview>.isWaitingForResponse() 返回 boolean — guest 页面是否正在等待页面主资源的首个响应。
  • <webview>.getWebContentsId() 返回 number — 该 webview 的 WebContents ID(元素尚未 attach 时会抛出错误,见 lib/renderer/web-view/web-view-element.ts)。

停止与刷新

  • <webview>.stop() — 停止任何进行中的导航。
  • <webview>.reload() — 重新加载 guest 页面。
  • <webview>.reloadIgnoringCache() — 忽略缓存地重新加载 guest 页面。
  • <webview>.isCrashed() 返回 boolean — 渲染进程是否已崩溃。

导航历史

  • <webview>.canGoBack() 返回 boolean — 是否可后退。
  • <webview>.canGoForward() 返回 boolean — 是否可前进。
  • <webview>.canGoToOffset(offset)offset Integer — 返回 boolean,是否可以跳到 offset
  • <webview>.clearHistory() — 清空导航历史。
  • <webview>.goBack() — 后退。
  • <webview>.goForward() — 前进。
  • <webview>.goToIndex(index)index Integer — 导航到指定的绝对索引。
  • <webview>.goToOffset(offset)offset Integer — 从"当前条目"导航到指定的偏移位置。

User Agent

  • <webview>.setUserAgent(userAgent)userAgent string — 覆盖 guest 页面的 user agent。
  • <webview>.getUserAgent() 返回 string — 获取 guest 页面的 user agent。

CSS 注入

  • <webview>.insertCSS(css)css string — 返回 Promise<string>:向当前页面注入 CSS,resolve 出可用于后续移除的样式表 key。
  • <webview>.removeInsertedCSS(key)key string — 返回 Promise<void>:按 insertCSS 返回的 key 移除注入的样式表,移除成功时 resolve。

JavaScript 执行

<webview>.executeJavaScript(code[, userGesture])

  • code string
  • userGesture boolean(可选)— 默认 false

返回 Promise<any> — resolve 为代码执行结果;若代码结果为 rejected promise 则 reject。在页面内执行 code。若设置 userGesture,会在页面内创建用户手势上下文,像 requestFullScreen 这类需要用户操作的 HTML API 可借助该选项完成自动化。

DevTools

  • <webview>.openDevTools() — 打开 guest 页面的 DevTools 窗口。
  • <webview>.closeDevTools() — 关闭 guest 页面的 DevTools 窗口。
  • <webview>.isDevToolsOpened() 返回 boolean — guest 页面是否已挂接 DevTools 窗口。
  • <webview>.isDevToolsFocused() 返回 boolean — guest 页面的 DevTools 窗口是否聚焦。
  • <webview>.inspectElement(x, y)x / y Integer — 开始检查 guest 页面 (x, y) 位置处的元素。
  • <webview>.inspectSharedWorker() — 打开 guest 页面中 shared worker 上下文的 DevTools。
  • <webview>.inspectServiceWorker() — 打开 guest 页面中 service worker 上下文的 DevTools。

音频控制

  • <webview>.setAudioMuted(muted)muted boolean — 静音/取消静音 guest 页面。
  • <webview>.isAudioMuted() 返回 boolean — guest 页面是否被静音。
  • <webview>.isCurrentlyAudible() 返回 boolean — 当前是否有音频正在播放。

文本编辑命令(Editing Commands)

以下方法在页面内执行对应编辑命令:

  • <webview>.undo() — 撤销
  • <webview>.redo() — 重做
  • <webview>.cut() — 剪切
  • <webview>.copy() — 复制
  • <webview>.centerSelection() — 将当前文本选区居中
  • <webview>.paste() — 粘贴
  • <webview>.pasteAndMatchStyle() — 匹配样式粘贴
  • <webview>.delete() — 删除
  • <webview>.selectAll() — 全选
  • <webview>.unselect() — 取消选择
  • <webview>.replace(text)text string — 替换
  • <webview>.replaceMisspelling(text)text string — 替换拼写错误的词
  • <webview>.insertText(text)text string — 返回 Promise<void>,向当前聚焦元素插入 text
  • <webview>.scrollToTop() — 滚动到当前 <webview> 顶部
  • <webview>.scrollToBottom() — 滚动到当前 <webview> 底部

<webview>.adjustSelection(options)

  • options Object
    • start Number(可选)— 当前选区起始索引的位移量
    • end Number(可选)— 当前选区结束索引的位移量

以给定位移量调整聚焦 frame 中当前文本选区的起点与终点。负值向文档开头移动,正值向文档结尾移动。示例见 webContents.adjustSelection

页面内查找

<webview>.findInPage(text[, options])

  • text string — 要搜索的内容,不能为空
  • options Object(可选)
    • forward boolean(可选)— 向前或向后查找,默认 true
    • findNext boolean(可选)— 本次请求是否开启新的查找会话;初次请求应为 true,后续请求为 false,默认 false
    • matchCase boolean(可选)— 是否区分大小写,默认 false

返回 Integer — 本次请求的 request id。启动一次页面内查找;结果通过订阅 found-in-page 事件获取。

<webview>.stopFindInPage(action)

  • action string — 结束 findInPage 请求时执行的动作:
    • clearSelection — 清除选区
    • keepSelection — 将选区转换为普通选区
    • activateSelection — 聚焦并点击选中节点

以指定 action 停止 webview 中任何进行中的 findInPage 请求。

打印与截图

<webview>.print([options])

  • options Object(可选)
    • silent boolean(可选)— 不向用户询问打印设置,默认 false
    • printBackground boolean(可选)— 打印背景色与背景图,默认 false
    • deviceName string(可选)— 打印机设备名,须为系统定义名而非“友好”名,例如 'Brother_QL_820NWB' 而非 'Brother QL-820NWB'
    • color boolean(可选)— 彩色或灰度打印,默认 true
    • margins Object(可选)
      • marginType string(可选)— 可为 defaultnoneprintableAreacustom;选 custom 时需同时指定 topbottomleftright
      • top / bottom / left / right number(可选)— 打印页边距(像素)
    • landscape boolean(可选)— 横向打印,默认 false
    • scaleFactor number(可选)— 缩放比例
    • pagesPerSheet number(可选)— 每张纸打印的页数
    • collate boolean(可选)— 是否逐份打印
    • copies number(可选)— 打印份数
    • pageRanges Object[](可选)— 打印页码范围
      • from number — 首页索引(0 起)
      • to number — 末页索引(含,0 起)
    • duplexMode string(可选)— 双面模式:simplexshortEdgelongEdge
    • dpi Record<string, number>(可选)— horizontal / vertical 分别为水平、垂直 dpi
    • header string(可选)— 打印为页眉的字符串
    • footer string(可选)— 打印为页脚的字符串
    • pageSize string | Size(可选)— 打印纸张大小:A3A4A5LegalLetterTabloid,或含 height(微米)的对象
    • usePrinterDefaultPageSize boolean(可选)— 使用系统默认纸型,默认 false;不能与 pageSize 同时使用。给出 deviceName 时用该打印机默认纸型,否则用系统默认打印机纸型;无法获取时回退 A4 (210mm × 297mm)

返回 Promise<void>。打印 webview 页面,与 webContents.print([options]) 等价。

<webview>.printToPDF(options)

返回 Promise<Uint8Array> — resolve 出生成的 PDF 数据。将 webview 页面打印为 PDF,与 webContents.printToPDF(options) 等价。

<webview>.capturePage([rect])

  • rect Rectangle(可选)— 捕获的页面区域

返回 Promise<NativeImage> — resolve 出一个 NativeImage。捕获 rect 内页面的快照;省略 rect 捕获整个可见页面。

消息通信

<webview>.send(channel, ...args)

  • channel string
  • ...args any[]

返回 Promise<void>。通过 channel 向渲染进程发送异步消息,可携带任意参数;渲染进程通过 ipcRenderer 监听 channel 事件处理消息。示例见 webContents.send

<webview>.sendToFrame(frameId, channel, ...args)

  • frameId [number, number] — [processId, frameId]
  • channel string
  • ...args any[]

返回 Promise<void>。与 send 类似但可定向到指定 frame。示例见 webContents.sendToFrame

输入事件

<webview>.sendInputEvent(event)

返回 Promise<void>。向页面发送一个输入事件。event 对象详细说明见 webContents.sendInputEvent

缩放

  • <webview>.setZoomFactor(factor)factor number — 把缩放因子设为指定值。缩放因子 = 缩放百分比 ÷ 100,所以 300% = 3.0。
  • <webview>.setZoomLevel(level)level number — 把缩放级别设为指定值。原始大小是 0,每增减 1 级代表放大/缩小 20%,默认限制为原大小的 300% 与 50%。公式为 scale := 1.2 ^ level

[!NOTE] Chromium 层的缩放策略是 same-origin:同一域名设置的缩放级别会传播到所有包含同域名的窗口实例。让窗口 URL 各不相同,即可实现按窗口缩放。

  • <webview>.getZoomFactor() 返回 number — 当前缩放因子。
  • <webview>.getZoomLevel() 返回 number — 当前缩放级别。
  • <webview>.setVisualZoomLevelLimits(minimumLevel, maximumLevel),参数为 number — 返回 Promise<void>,设置双指捏合缩放的上下限。

其他

  • <webview>.showDefinitionForSelection() macOS — 显示查询页面所选单词的弹出词典。

DOM 事件

以下 DOM 事件对 <webview> 元素可用。除 load-commit-focus-change 等由渲染层合成转发外,多数事件由主进程根据 guest WebContents 的回调派发,最终由 lib/renderer/web-view/web-view-impl.tsdispatchEvent 转成普通 DOM 事件在 webview 节点上触发(参数被 Object.assignevent 上)。此外每个事件还可通过 on<event> 属性风格绑定(setupEventProperty,见 lib/renderer/web-view/web-view-impl.ts)。

导航与加载生命周期

  • load-commit — 返回 url string、isMainFrame boolean。一次加载提交时触发,包括当前文档内的导航以及子 frame 的 document 级加载,但不包括异步资源加载。主 frame 的 load-commit 还会让渲染层回写 src 属性(onLoadCommit)。
  • did-finish-load — 导航完成时触发,即标签页转圈动画停止且 onload 事件派发。
  • did-fail-load — 返回 errorCode Integer、errorDescription string、validatedURL string、isMainFrame boolean。与 did-finish-load 类似,但在加载失败或被取消时触发(例如调用了 window.stop())。
  • did-frame-finish-load — 返回 isMainFrame boolean。某个 frame 完成导航时触发。
  • did-start-loading — 对应标签页转圈动画开始的时刻。
  • did-stop-loading — 对应标签页转圈动画停止的时刻。
  • dom-ready — 指定 frame 中的 document 加载完成时触发。
  • did-attach — 附着(attach)到 embedder web contents 时触发。

页面标题与图标

  • page-title-updated — 返回 title string、explicitSet boolean。导航期间设置页面标题时触发;当标题是从文件 URL 合成时 explicitSetfalse
  • page-favicon-updated — 返回 favicons string[](URL 数组)。页面收到 favicon URL 时触发。
  • did-change-theme-color — 返回 themeColor string。页面主题色改变时触发,通常因遇到如下 meta 标签:
<meta name='theme-color' content='#ff0000'>

全屏

  • enter-html-full-screen — 页面通过 HTML API 进入全屏时触发。
  • leave-html-full-screen — 页面通过 HTML API 退出全屏时触发。

控制台消息

  • console-message — 返回 level Integer(0~3,依次对应 verboseinfowarningerror)、message string(实际控制台消息)、line Integer(触发该消息的源码行号)、sourceId string。guest 窗口记录控制台消息时触发。以下示例把所有日志消息转发到 embedder 控制台(不区分级别):
const webview = document.querySelector('webview')
webview.addEventListener('console-message', (e) => {
  console.log('Guest page logged a message:', e.message)
})

页面内查找结果

  • found-in-page — 返回 result Object:
    • requestId Integer
    • activeMatchOrdinal Integer — 当前活动匹配的位置
    • matches Integer — 匹配总数
    • selectionArea Rectangle — 首个匹配区域坐标
    • finalUpdate boolean

webview.findInPage 请求有结果可用时触发。

const webview = document.querySelector('webview')
webview.addEventListener('found-in-page', (e) => {
  webview.stopFindInPage('keepSelection')
})

const requestId = webview.findInPage('test')
console.log(requestId)

导航相关事件

  • will-navigate — 返回 url string。当用户或页面想要开始导航时触发,例如 window.location 对象改变或用户点击页面内链接。使用 loadURLback 等 API 编程式启动的导航不会触发该事件;页内导航(点击锚点链接或更新 window.location.hash)也不触发,应改用 did-navigate-in-page。调用 event.preventDefault() 无效
  • will-frame-navigate — 返回 url string、isMainFrame boolean、frameProcessId Integer、frameRoutingId Integer。当用户或页面想要在 <webview> 或其内嵌的任何 frame 中开始导航时触发。触发/不触发情形与 will-navigate 相同,preventDefault() 同样无效。
  • did-start-navigation — 返回 url string、isInPlace boolean、isMainFrame boolean、frameProcessId Integer、frameRoutingId Integer。任何 frame(含主 frame)开始导航时触发;页内导航的 isInPlacetrue
  • did-redirect-navigation — 返回参数同 did-start-navigation。导航期间发生服务端重定向(如 302)后触发。
  • did-navigate — 返回 url string。一次导航完成时触发。页内导航不触发,应使用 did-navigate-in-page
  • did-frame-navigate — 返回 url string、httpResponseCode Integer(非 HTTP 导航为 -1)、httpStatusText string(非 HTTP 导航为空)、isMainFrame boolean、frameProcessId Integer、frameRoutingId Integer。任意 frame 的导航完成时触发,页内导航不触发。
  • did-navigate-in-page — 返回 isMainFrame boolean、url string。页内导航发生时触发——页面 URL 变化但不触发页面外导航,例如点击锚点链接或触发 DOM hashchange 事件时。

窗口关闭与渲染进程

  • close — guest 页面尝试关闭自身时触发。以下示例在 guest 尝试自关时把 webview 导航到 about:blank
const webview = document.querySelector('webview')
webview.addEventListener('close', () => {
  webview.src = 'about:blank'
})
  • render-process-gone — 返回 details RenderProcessGoneDetails。渲染进程意外消失时触发,通常是被崩溃或被杀。
  • destroyed — WebContents 被销毁时触发。

媒体

  • media-started-playing — 媒体开始播放时触发。
  • media-paused — 媒体暂停或播放完毕时触发。

链接预览与 DevTools

  • update-target-url — 返回 url string。鼠标移到链接上或键盘将焦点移到链接上时触发。
  • devtools-open-url — 返回 url string。在 DevTools 中点击链接,或在其右键菜单中对链接选择 "Open in new tab" 时触发。
  • devtools-search-query — 返回 query string。在右键菜单中对其文本选择 "Search" 时触发。
  • devtools-opened — DevTools 打开时触发。
  • devtools-closed — DevTools 关闭时触发。
  • devtools-focused — DevTools 聚焦/打开时触发。

embedder 与 guest 通信

  • ipc-message — 返回 frameId [number, number]([processId, frameId] 对)、channel string、args any[]。guest 页面向 embedder 页面发送异步消息时触发。

配合 sendToHost 方法与 ipc-message 事件即可在 guest 与 embedder 之间双向通信:

// In embedder page.
const webview = document.querySelector('webview')
webview.addEventListener('ipc-message', (event) => {
  console.log(event.channel)
  // Prints "pong"
})
webview.send('ping')
// In guest page.
const { ipcRenderer } = require('electron')

ipcRenderer.on('ping', () => {
  ipcRenderer.sendToHost('pong')
})

右键菜单

  • context-menu — 返回 params Object。出现需要处理的新右键菜单时触发,参数非常丰富:
    • x / y Integer — 坐标
    • linkURL string — 触发菜单所在节点外层链接的 URL
    • linkText string — 链接关联文本;若链接内容是图片则可能为空字符串
    • pageURL string — 触发菜单所在顶层页面的 URL
    • frameURL string — 触发菜单所在子 frame 的 URL
    • srcURL string — 触发菜单元素的源 URL(有源 URL 的元素包括图片、音频与视频)
    • mediaType string — 节点类型:noneimageaudiovideocanvasfileplugin
    • hasImageContents boolean — 是否在含非空内容的图片上触发
    • isEditable boolean — 上下文是否可编辑
    • selectionText string — 触发菜单的选区文本
    • titleText string — 触发菜单选区的 title 文本
    • altText string — 触发菜单选区的 alt 文本
    • suggestedFilename string — 通过右键菜单 "Save Link As" 保存文件时建议的文件名
    • selectionRect Rectangle — 文档坐标系中选区范围的矩形
    • selectionStartOffset number — 选区文本的起始位置
    • referrerPolicy Referrer — 触发菜单所在 frame 的 referrer policy
    • misspelledWord string — 光标下的拼写错误单词(若有)
    • dictionarySuggestions string[] — 用于替换 misspelledWord 的建议词数组;仅当存在拼写错误词且启用拼写检查时可用
    • frameCharset string — 触发菜单所在 frame 的字符编码
    • formControlType string — 触发菜单的来源控件类型,可能值包括 nonebutton-buttonfield-setinput-buttoninput-checkboxinput-colorinput-dateinput-datetime-localinput-emailinput-fileinput-hiddeninput-imageinput-monthinput-numberinput-passwordinput-radioinput-rangeinput-resetinput-searchinput-submitinput-telephoneinput-textinput-timeinput-urlinput-weekoutputreset-buttonselect-listselect-multipleselect-onesubmit-buttontext-area
    • spellcheckEnabled boolean — 若上下文可编辑,是否启用拼写检查
    • menuSourceType string — 触发右键菜单的输入来源:nonemousekeyboardtouchtouchMenulongPresslongTaptouchHandlestylusadjustSelectionadjustSelectionReset
    • mediaFlags Object — 触发菜单的媒体元素标志:
      • inError boolean — 媒体元素是否已崩溃
      • isPaused boolean — 是否暂停
      • isMuted boolean — 是否静音
      • hasAudio boolean — 是否有音频
      • isLooping boolean — 是否循环
      • isControlsVisible boolean — 控件是否可见
      • canToggleControls boolean — 控件是否可切换
      • canPrint boolean — 是否可打印
      • canSave boolean — 是否可下载
      • canShowPictureInPicture boolean — 是否可画中画
      • isShowingPictureInPicture boolean — 当前是否在画中画
      • canRotate boolean — 是否可旋转
      • canLoop boolean — 是否可循环
    • editFlags Object — 渲染进程自认能执行对应操作的能力标志:
      • canUndo / canRedo / canCut / canCopy / canPaste / canDelete / canSelectAll boolean — 是否能执行对应编辑动作
      • canEditRichly boolean — 是否能富文本编辑

总结与建议

综合文档与源码,<webview> 提供了一套相当完整的"应用内嵌外部内容"能力矩阵:

  • 隔离性:guest 运行在独立进程与独立 frame,默认无 Node 集成、无插件、无弹窗,配合 partition 可精细控制会话边界;
  • 可控性:导航、历史、缩放、打印、DevTools、音频、页面查找、CSS/JS 注入、双向 IPC 一应俱全;
  • 可观测性:从导航生命周期、控制台、右键菜单到渲染进程崩溃等各类 DOM 事件覆盖了绝大多数调试与功能场景。

在决定技术选型时,请务必再次权衡官方警告:受 Chromium webview 架构持续演进的稳定性影响,优先评估 <iframe>WebContentsView 等替代方案。若坚持使用,建议将 webview 相关页面集中在少数受控场景,并参考仓库测试 spec/webview-spec.tswebview-tag API 结构定义 里没有覆盖到的运行时细节前,先在目标 Electron 版本上做充分验证。

登录后查看全文
热门项目推荐
相关项目推荐