跳到主要内容

Webview

webview-tag

webview 标签

Electron 提供了 webview 标签,用来嵌入 Web 页面:作用上类似于 HTML 里的 iframe 标签,但跑在独立进程中,主要出于安全性考虑。

从应用场景来看,类似于于 Android 的 WebView,外部对嵌入页面的控制权较大,包括 CSS/JS 注入、资源拦截等,而嵌入页面对外部的影响很小,是个相对安全的沙盒。

webContents

像 BrowserWindow 一样,webview 也拥有与之关联的 webContents 对象。本质上,webContents 是个 EventEmitter,用来连通页面与外部环境。

控制 webview 显示隐藏

常规做法是 webview.style.display = hidden ? 'none' : '',但会引发一些奇怪的问题,比如页面内容区域变小了。大致原因是不允许重写 webview 的 display 值,只能是 flex/inline-flex,其它值会引发奇怪问题

官方建议采用:visibility: hidden来隐藏 webview,但仍然占据空间,不一定能满足布局需要。社区有一种替代 display: none 的方法:

webview.hidden {
width: 0px;
height: 0px;
flex: 0 1;
}

导出 Console 信息

对于注入 JS 的场景,为了方便调试,可以通过 webview 的 console-message 事件拿到 Console 信息:

// Export console message
webview.addEventListener("console-message", (e) => {
console.log("webview: " + e.message);
});

能满足一般调试需要,但缺陷是,消息是跨进程通信传过来的,所以 e.message 会被强转字符串,所以输出的对象会变成 toString() 后的 [object Object]

webview 与 renderer 通信

有内置的 IPC 机制,简单方便,例如:

// renderer 环境,接受关键字是 ipc-message
webview.addEventListener("ipc-message", (event) => {
console.log(event.channel);
});
webview.send("our-secrets", "ping");

// webview环境
const { ipcRenderer } = require("electron");
ipcRenderer.on("our-secrets", (e, message) => {
console.log(message);
ipcRenderer.sendToHost("pong pong");
});

如果处理了上一条提到的 console-message 事件,将看到 Console 输出:

webview: ping
pong pong

前进/后退/刷新/地址跳转

webview 默认没有提供这些控件(不像 video 标签之类的),但提供了用来实现这些行为的 API,如下:

// Forwards
if (webview.canGoForward()) {
webview.goForward();
}
// Backwords
if (webview.canGoBack()) {
webview.goBack();
}
// Refresh
webview.reload();
// loadURL
webview.loadURL(url);