ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 24.2.`<webview>` 标签 > 在一个单独的 frame 和 进程中显示外部 web 内容。 使用 `webview` 标签来嵌入'guest' 内容 (比如 web 页面)到你的 Electron 应用。这个访客内容包含在 `webview` 容器内。 应用中一个嵌入的页面控制访客内容如何陈列和渲染。 不像一个 `iframe` , `webview` 运行在一个相对你的 app 独立的进程中。在你的 app 中,它和你的 web 页面并没有相同的权限,并且所有你的应用和嵌入内容之间的交互都会是异步的。这使得你的应用从嵌入内容之间保持安全。 出于安全目的, `webview` 只能被用在启用了 `nodeIntegration` 的 `BrowserWindow` 中。 ## 示例 要嵌入一个 web 页面到你的 app ,添加 `webview` 标签到 app 的嵌入页面(指app 中用于显示访客内容的页面)。以这种简单的形式, `webview` 标签包含了 web 页面的 `src` 和控制 `webview`容器外观的 css 样式: ```html <webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview> ``` 如果你想以某种方式控制访客内容,可以编写监听 `webview` 事件的 JavaScript ,并使用 `webview` 的方法响应这些事件。这里是两个监听器的示例代码:一个监听 web 页面开始载入,另一个监听 web 页面停止加载,并在载入过程中显示一个 "loading..." 消息: ```html <script> onload = () => { const webview = document.getElementById('foo') 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> ``` ## CSS 样式注意 注意,当使用传统的和适应的布局(从 v 0.36.11起), `webview` 标签的样式在内部使用 `display:flex;` 来确保子 `object` 元素填充完整的 `webview` 容器的宽高度。不要覆盖默认的 `display:flex;` CSS 属性,除非对于内联布局声明 `display:inline-flex;` 。 `webview` 在被使用 `hidden` 属性或使用 `display: none;` 隐藏时会有些问题。这可能在它的子 `browserplugin` 对象中引发不常见的渲染行为,而且 web 页面被重载,当 `webview` 未被隐藏,而不仅是再次可见。建议的方案是使用 CSS 置 0 `webview` 的宽度和高度来隐藏它, 并允许元素通过 `flex` 缩小到 0 范围。 ```html <style> webview { display:inline-flex; width:640px; height:480px; } webview.hide { flex: 0 1; width: 0px; height: 0px; } </style> ``` ## 标签属性 `webview` 标签有以下属性: ### `src` ```html <webview src="https://www.github.com/"></webview> ``` 返回可见的 URL 。写到这个属性初始化顶部导航。 赋值 `src` 它自己的值将会重新载入当前页面。. `src` 属性也可以接受 data URLs,如 `data:text/plain,Hello, world!`. ### `autosize` ```html <webview src="https://www.github.com/" autosize="on" minwidth="576" minheight="432"></webview> ``` 如果为 "on", `webview` 容器会自动根据属性 `minwidth`,`minheight`, `maxwidth` 和 `maxheight` 指定的边界内自动重设大小。这些约束不影响 `webview` ,除非 `autosize` 被启用。当 `autosize` 被启用, `webview` 容器尺寸不能小于最小值或大于最大值。 ### `nodeintegration` ```html <webview src="http://www.google.com/" nodeintegration></webview> ``` 如果为 "on",`webview` 中的访客页面将有 node 集成,并可以使用 node APIs,像 `require` 和 `process` 来访问底层系统资源。 ### `plugins` ```html <webview src="https://www.github.com/" plugins></webview> ``` 如果开启,`webview` 中的访客页面可以使用浏览器插件。 ### `preload` ```html <webview src="https://www.github.com/" preload="./test.js"></webview> ``` 指定一个脚本,将会在运行于访客页面中的其它脚本被载入之前加载。脚本的 URL 协议必须是 `file:` 或者 `asar:`,因为它在表面之下将被通过 `require` 加载到访客页面。 当访客页面没有 node 集成,这个脚本仍然有权限访问所有 Node APIs,但是被 Node 注入的全局对象会在这个脚本执行完成之后删除。 ### `httpreferrer` ```html <webview src="https://www.github.com/" httpreferrer="http://cheng.guru"></webview> ``` 设置访客页面的 referrer URL。 ### `useragent` ```html <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> ``` 在页面被导航之前设置访客页面的用户代理。一旦页面被加载,使用 `setUserAgent` 方法来改变用户代理。 ### `disablewebsecurity` ```html <webview src="https://www.github.com/" disablewebsecurity></webview> ``` 如果开启,访客页面 web安全将被禁用。 ### `partition` ```html <webview src="https://github.com" partition="persist:github"></webview> <webview src="http://electron.atom.io" partition="electron"></webview> ``` 设置页面使用的会话。如果 `partition` 以 `persist:` 开始,页面会使用一个持续可用的会话到 app 中所有使用相同 `partition` 的页面。如果没有 `persist:` 前缀,页面会使用一个内存中的会话。通过分配相同的 `partition`,多个页面可以共享相同的会话。如果 `partition` 未设置,那么应用默认的会话被使用。 这个值只能在第一次导航之前被修改,因为一个活动渲染器进程的会话不能改变。后续的修改这个值的企图会失败,抛出一个 DOM 异常。 ### `allowpopups` ```html <webview src="https://www.github.com/" allowpopups></webview> ``` 如果开启,访客页面会被允许打开新窗口。 ### `webpreferences` ```html <webview src="https://github.com" webpreferences="allowDisplayingInsecureContent, javascript=no"></webview> ``` 一个字符串列表,指定设置 `webview` 上的 web 首选项,通过`,` 分隔。 支持的首选项完整列表可以在 [BrowserWindow](browser-window.md#new-browserwindowoptions) 中查看。 字符串依照和作为在 `window.open` 中的功能相同的格式。 一个名字本身被给定一个 `true` 的布尔值。 一个首选项可以通过 `=` 设置为另一个值。 特别的值 `yes` 和 `1` 被解释为 `true`,而 `no` 和 `0` 被解释为 `false`。 ### `blinkfeatures` ```html <webview src="https://www.github.com/" blinkfeatures="PreciseMemoryInfo, CSSVariables"></webview> ``` 指定 blink 功能被启用的一个字符串列表,使用 `,` 分隔。 支持功能的字符串完整列表可以在 [RuntimeEnabledFeatures.in][blink-feature-string] 文件中找到。 ### `disableblinkfeatures` ```html <webview src="https://www.github.com/" disableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview> ``` 指定 blink 功能被禁用的字符串列表,使用 `,` 分隔。 支持功能的字符串完整列表可以在 [RuntimeEnabledFeatures.in][blink-feature-string] 文件中找到。 ### `guestinstance` ```html <webview src="https://www.github.com/" guestinstance="3"></webview> ``` 连接 `webview` 到一个指定的 webContents 的值。当一个 `webview` 第一次载入一个新的 webContent 被创建,这个属性被设置为它的示例 标识。为一个新的或者已存在的 webview 设置这个属性,连接它到当前渲染其中另一个不同的 webview 中已存在的 webContents。 已存在的 webview 将会看到 `destroy` 事件,然后当一个新的 url 被载入将创建一个新的 webContents 。 ## 方法 `webview` 标签有以下方法: **注意:** `webview` 元素必须在使用这些方法之前被加载。 **示例** ```javascript const webview = document.getElementById('foo') webview.addEventListener('dom-ready', () => { webview.openDevTools() }) ``` ### `<webview>.loadURL(url[, options])` * `url` URL * `options` Object (可选) * `httpReferrer` String —— 一个 HTTP Referrer url。 * `userAgent` String —— 发起请求的一个用户代理。 * `extraHeaders` String —— 通过 "\n" 分隔的额外的 headers。 在 webview 中加载 `url` , `url` 必须包含协议前缀。例如, `http://` 或 `file://`。 ### `<webview>.getURL()` 返回 `String` —— 访客页面的 URL。 ### `<webview>.getTitle()` 返回 `String` —— 访客页面的标题。 ### `<webview>.isLoading()` 返回 `Boolean` —— 访客页面是否还在加载资源。 ### `<webview>.isWaitingForResponse()` 返回 `Boolean` —— 访客页面是否正在等待一个页面上主资源的 first-response。 ### `<webview>.stop()` 停止任何正在等待的导航。 ### `<webview>.reload()` 重新载入访客页面。 ### `<webview>.reloadIgnoringCache()` 重新载入访客页面并忽略缓存。 ### `<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 导航到指定的相对于当前页的偏移。 ### `<webview>.isCrashed()` 返回 `Boolean` —— 渲染器进程是否崩溃。 ### `<webview>.setUserAgent(userAgent)` * `userAgent` String 重写访客页面的用户代理。 ### `<webview>.getUserAgent()` 返回 `String` —— 访客页面的用户代理。 ### `<webview>.insertCSS(css)` * `css` String 注入 CSS 到访客页面。 ### `<webview>.executeJavaScript(code, userGesture, callback)` * `code` String * `userGesture` Boolean —— 默认为 `false`. * `callback` Function (可选) —— 脚本被执行后调用。 * `result` Any 在页面中执行 `code` 。如果 `userGesture` 被设置,它将在页面中创建用户的手势上下文。需要用户操作的 HTML APIs 如 `requestFullScreen`, 可以利用这个选项的优势来自动完成。 ### `<webview>.openDevTools()` 打开访客页面的 开发者工具窗口。 ### `<webview>.closeDevTools()` 关闭访客页面的开发者工具窗口。 ### `<webview>.isDevToolsOpened()` 返回 `Boolean` —— 访客页面是否附加了一个开发者工具窗口。 ### `<webview>.isDevToolsFocused()` 返回 `Boolean` —— 访客页面的开发者工具窗口是否获得焦点。 ### `<webview>.inspectElement(x, y)` * `x` Integer * `y` Integer 开始检查在访客页面中 (`x`, `y`) 位置的元素。 ### `<webview>.inspectServiceWorker()` 为出现在访客页面中的服务 worker 上下文打开开发者工具。 ### `<webview>.setAudioMuted(muted)` * `muted` Boolean 设置访客页面静音。 ### `<webview>.isAudioMuted()` 返回 `Boolean` —— 访客页面是否被静音。 ### `<webview>.undo()` 在页面中执行编辑命令 `undo`。 ### `<webview>.redo()` 在页面中执行编辑命令 `redo`。 ### `<webview>.cut()` 在页面中执行编辑命令 `cut`。 ### `<webview>.copy()` 在页面中执行编辑命令 `copy`。 ### `<webview>.paste()` 在页面中执行编辑命令 `paste` 。 ### `<webview>.pasteAndMatchStyle()` 在页面中执行编辑命令 `pasteAndMatchStyle` 。 ### `<webview>.delete()` 在页面中执行编辑命令 `delete`。 ### `<webview>.selectAll()` 在页面中执行编辑命令 `selectAll` 。 ### `<webview>.unselect()` 在页面中执行编辑命令 `unselect`。 ### `<webview>.replace(text)` * `text` String 在页面中执行编辑命令 `replace`。 ### `<webview>.replaceMisspelling(text)` * `text` String 在页面中执行编辑命令 `replaceMisspelling`。 ### `<webview>.insertText(text)` * `text` String 插入 `text` 到获得焦点的元素。 ### `<webview>.findInPage(text[, options])` * `text` String —— 要搜索的内容,不能为空。 * `options` Object (可选) * `forward` Boolean —— 是向前或者向后搜索,默认为 `true`。 * `findNext` Boolean —— 操作是第一次请求还是一个跟随的步骤,默认为 `false`。 * `matchCase` Boolean —— 是否大小写敏感,默认为 `false`。 * `wordStart` Boolean —— 是否只查找单词的开头,默认为 `false`。 * `medialCapitalAsWordStart` Boolean —— 当结合使用 `wordStart`时,接受一个匹配在单词的中间,如果匹配是一个大写字符开始后跟小写或者没有其它字母。接受几个其它的词内匹配,默认为 `false`。 开始一个请求在 web 页面中查找所有关于 `text` 的匹配,并返回一个 `Integer` 代表这个请求的请求 id。请求的结果可以被通过订阅 [`found-in-page`](web-view-tag.md#event-found-in-page) 事件来获得。 ### `<webview>.stopFindInPage(action)` * `action` String —— 当 [`<webview>.findInPage`](web-view-tag.md#webviewtagfindinpage) 请求结束之后指定一个动作发生。 * `clearSelection` —— 清空所选。 * `keepSelection` —— 转换选择到一个正常的选择。 * `activateSelection` —— 获得焦点并点击选定节点。 为 `webview` 使用提供的 `action` 停止任何 `findInPage` 请求。 ### `<webview>.print([options])` 打印 `webview` 的 web 页面。和 `webContents.print([options])` 相同。 ### `<webview>.printToPDF(options, callback)` 打印 `webview` 的 web 页面为 PDF,和 `webContents.printToPDF(options, callback)` 一样。 ### `<webview>.capturePage([rect, ]callback)` 捕捉一个 `webview` 的页面截图。和 `webContents.capturePage([rect, ]callback)` 一样。 ### `<webview>.send(channel[, arg1][, arg2][, ...])` * `channel` String * `arg` (可选) 通过 `channel` 发送一个异步消息到渲染进程,你也可以发送任意参数。渲染进程可以通过使用 `ipcRender` 模块监听 `channel` 事件来处理消息。 查看 [webContents.send](web-contents.md#webcontentssendchannel-args) 中的示例。 ### `<webview>.sendInputEvent(event)` * `event` Object 发送一个输入的 `event` 到页面。 查看 [webContents.sendInputEvent](web-contents.md#webcontentssendinputeventevent) 了解 `event` 对象的详细描述。 ### `<webview>.setZoomFactor(factor)` * `factor` Number —— 缩放系数。 改变缩放系数到指定值。缩放系数通过浮点数表示,如 3.0 = 300%。 ### `<webview>.setZoomLevel(level)` * `level` Number —— Zoom 级别 改变缩放级别到指定值。原始大小是 0 ,每次增加或者减少表示相对默认缩放了 20%,分别限制为原始尺寸的 300% 和 50% 。 ### `<webview>.showDefinitionForSelection()` _macOS_ 显示在页面上搜索选定单词的弹出字典。 ### `<webview>.getWebContents()` 返回 `WebContents` —— 这个 `webview` 相关的 [WebContents](web-contents.md) 。 ## DOM 事件 以下 DOM 事件 在 `webview` 标签中可用: ### Event: 'load-commit' 返回: * `url` String * `isMainFrame` Boolean 当一个加载完成后触发。 这个包含当前文档的导航和 subframe 文档级的加载,但是不包含异步资源加载。 ### Event: 'did-finish-load' 在导航加载完成时触发,也就是 tab 的 spinner 停止 spinning 时,并且 `onload` 事件被发出后。 ### Event: 'did-fail-load' 返回: * `errorCode` Integer * `errorDescription` String * `validatedURL` String * `isMainFrame` Boolean 这个事件和 `did-finish-load` 很像,但是当加载失败或者被取消时触发,即 `window.stop()` 被调用。 ### Event: 'did-frame-finish-load' 返回: * `isMainFrame` Boolean 当一个 frame 完成导航之后触发。 ### Event: 'did-start-loading' 对应时间点为当 tab 的 spinner开始 spinning 时。 ### Event: 'did-stop-loading' 对应时间点为当 tab 的 spinner 停止 spinning 时。 ### Event: 'did-get-response-details' 返回: * `status` Boolean * `newURL` String * `originalURL` String * `httpResponseCode` Integer * `requestMethod` String * `referrer` String * `headers` Object * `resourceType` String 当关于一个请求的资源的明细可用时被触发。 `status` 表示 socket 连接下载该资源。 ### Event: 'did-get-redirect-request' 返回: * `oldURL` String * `newURL` String * `isMainFrame` Boolean 请求一个资源时当一个重定向被接收到时触发。 ### Event: 'dom-ready' 当给定 frame 中的文档被加载后触发。 ### Event: 'page-title-updated' 返回: * `title` String * `explicitSet` Boolean 当页面标题在导航期间被设置后触发。 `explicitSet` 在标题从文件 URL 合成时为 `false` 。 ### Event: 'page-favicon-updated' 返回: * `favicons` String[] - Array of URLs. 当页面接收到 favicon urls 时被触发。 ### Event: 'enter-html-full-screen' 当页面进入被 HTML API 触发的全屏时触发。 ### Event: 'leave-html-full-screen' 当页面被 HTML API 触发离开全屏时触发。 ### Event: 'console-message' 返回: * `level` Integer * `message` String * `line` Integer * `sourceId` String 当访客窗口记录了一个 控制台消息时触发。 下面的示例代码转发所有日志消息到嵌入者的控制台,不考虑日志级别或者其它属性。 ```javascript const webview = document.getElementById('foo') webview.addEventListener('console-message', (e) => { console.log('Guest page logged a message:', e.message) }) ``` ### Event: 'found-in-page' 返回: * `result` Object * `requestId` Integer * `activeMatchOrdinal` Integer —— 激活的匹配的位置。 * `matches` Integer —— 匹配的数量。 * `selectionArea` Object —— 第一个匹配区域的坐标。 当 [`webview.findInPage`](web-view-tag.md#webviewtagfindinpage) 请求的一个结果可用时触发。 ```javascript const webview = document.getElementById('foo') webview.addEventListener('found-in-page', (e) => { webview.stopFindInPage('keepSelection') }) const requestId = webview.findInPage('test') console.log(requestId) ``` ### Event: 'new-window' 返回: * `url` String * `frameName` String * `disposition` String —— 可能是 `default`, `foreground-tab`, `background-tab`, `new-window`, `save-to-disk` 和`other`。 * `options` Object —— 被用来创建新的 `BrowserWindow` 的选项。 当访客页面试图打开一个新的浏览器窗口时触发。 如下示例代码使用系统默认的浏览器打开新的 url 。 ```javascript const {shell} = require('electron') const webview = document.getElementById('foo') webview.addEventListener('new-window', (e) => { const protocol = require('url').parse(e.url).protocol if (protocol === 'http:' || protocol === 'https:') { shell.openExternal(e.url) } }) ``` ### Event: 'will-navigate' 返回: * `url` String 当一个用户或者页面想要开始导航时发射。当 `window.location` 对象被改变或者用户点击了页面中一个链接时都可能发生。 这个事件在使用 如 `<webview>.loadURL` 和 `<webview>.back` APIs 以编程方式开始导航的时候不会触发。 在页面内的导航也不会被触发,比如点击锚点链接,或者更新 `window.location.hash`。应该使用 `did-navigate-in-page` 事件处理这个目的。 调用 `event.preventDefault()` 不会有任何效果。 ### Event: 'did-navigate' 返回: * `url` String 当一个导航做出时被触发。 这个事件对于页面内的导航不会被发射,比如点击锚点或者更新 `window.location.hash`。应该使用 `did-navigate-in-page` 事件处理这个目的。 ### Event: 'did-navigate-in-page' 返回: * `isMainFrame` Boolean * `url` String 当一个页面内导航发生时触发。 当页面内的导航发生,页面的 URL 改变但是不会导航出这个页面。例如当锚点链接被点击,或者 DOM 的 `hashchange` 事件被触发。 ### Event: 'close' 当访客页面试图关闭它自己时触发。 以下示例代码在访客试图关闭它自身时导航 `webview` 到 `about:blank`。 ```javascript const webview = document.getElementById('foo') webview.addEventListener('close', () => { webview.src = 'about:blank' }) ``` ### Event: 'ipc-message' 返回: * `channel` String * `args` Array 当访客页面已经发送一个异步消息给嵌入者页面时触发。 使用 `sendToHost` 方法和 `ipc-message` 事件,你可以简单的在访客页面和嵌入者页面之间通讯: ```javascript // In embedder page. const webview = document.getElementById('foo') webview.addEventListener('ipc-message', (event) => { console.log(event.channel) // Prints "pong" }) webview.send('ping') ``` ```javascript // In guest page. const {ipcRenderer} = require('electron') ipcRenderer.on('ping', () => { ipcRenderer.sendToHost('pong') }) ``` ### Event: 'crashed' 当渲染进程崩溃时触发。 ### Event: 'gpu-crashed' 当 gpu 进程崩溃时触发。 ### Event: 'plugin-crashed' 返回: * `name` String * `version` String 当一个插件进程崩溃时触发。 ### Event: 'destroyed' 当 WebContents 被销毁时触发。 ### Event: 'media-started-playing' 当媒体开始播放时触发。 ### Event: 'media-paused' 当媒体暂停或者继续播放时触发。 ### Event: 'did-change-theme-color' 返回: * `themeColor` String 当一个页面的主题颜色改变时触发。这通常通过遇到一个 meta 标签: ```html <meta name='theme-color' content='#ff0000'> ``` ### Event: 'update-target-url' 返回: * `url` String 当鼠标移动到一个链接或者键盘移动焦点到一个链接时触发。 ### Event: 'devtools-opened' 当开发者工具被打开时触发。 ### Event: 'devtools-closed' 当开发者工具被关闭时触发。 ### Event: 'devtools-focused' 当开发者工具打开/获得焦点时触发。 参考:[blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in