从渲染器打开窗口
有几种方法可以控制从渲染器中的可信或不可信内容创建窗口的方式。窗口可以通过以下两种方式从渲染器创建:
- 点击带有
target=_blank属性的链接或提交表单 - JavaScript 调用
window.open()
对于同源内容,新窗口将在同一进程中创建,从而使父窗口可以直接访问子窗口。这对于充当首选项面板或类似功能的应用程序子窗口非常有用,因为父窗口可以直接渲染到子窗口,就像它是父窗口中的 div 一样。这与浏览器中的行为相同。
Electron 在底层将此原生 Chrome Window 与 BrowserWindow 配对。您可以通过使用 webContents.setWindowOpenHandler() 来自渲染器创建的窗口,来利用在主进程中创建 BrowserWindow 时可用的所有自定义选项。
BrowserWindow 构造函数选项的设置优先级,按递增顺序为:从 window.open() 的 features 字符串解析的选项、从父窗口继承的安全相关 webPreferences,以及由 webContents.setWindowOpenHandler 给定的选项。请注意,webContents.setWindowOpenHandler 拥有最终决定权和完全权限,因为它是在主进程中调用的。
window.open(url[, frameName][, features])
urlstringframeName字符串(可选)features字符串(可选)
返回 Window | null
features 是一个逗号分隔的键值列表,遵循浏览器标准的格式。Electron 会尽可能从该列表中解析 BrowserWindowConstructorOptions,以方便使用。为了获得完全控制和更好的易用性,请考虑使用 webContents.setWindowOpenHandler 来自定义 BrowserWindow 的创建。
可以从 features 字符串中直接设置一部分 WebPreferences:zoomFactor、nodeIntegration、javascript、contextIsolation 和 webviewTag。
例如
window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIntegration=no')
备注
- 如果父窗口禁用了 Node 集成,则打开的
window中的 Node 集成将始终被禁用。 - 如果父窗口启用了上下文隔离,则打开的
window中的上下文隔离将始终被启用。 - 如果父窗口禁用了 JavaScript,则打开的
window中的 JavaScript 将始终被禁用。 - 在
features中给定的非标准功能(未由 Chromium 或 Electron 处理)将被传递给任何已注册的webContents的did-create-window事件处理程序,作为options参数。 frameName遵循 原生文档 中target的规范。- 当打开
about:blank时,子窗口的WebPreferences将从父窗口复制,并且无法覆盖它,因为 Chromium 在这种情况下会跳过浏览器端导航。
要自定义或取消窗口的创建,您可以选择使用主进程中的 webContents.setWindowOpenHandler() 设置覆盖处理程序。返回 { action: 'deny' } 将取消窗口。返回 { action: 'allow', overrideBrowserWindowOptions: { ... } } 将允许打开窗口并设置用于创建窗口的 BrowserWindowConstructorOptions。请注意,这比通过 feature 字符串传递选项更强大,因为渲染器在决定安全首选项方面权限比主进程更有限。
除了传递 action 和 overrideBrowserWindowOptions 之外,还可以传递 outlivesOpener,例如:{ action: 'allow', outlivesOpener: true, overrideBrowserWindowOptions: { ... } }。如果设置为 true,则新创建的窗口在启动窗口关闭时不会关闭。默认值为 false。
原生 Window 示例
// main.js
const mainWindow = new BrowserWindow()
// In this example, only windows with the `about:blank` url will be created.
// All other urls will be blocked.
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
if (url === 'about:blank') {
return {
action: 'allow',
overrideBrowserWindowOptions: {
frame: false,
fullscreenable: false,
backgroundColor: 'black',
webPreferences: {
preload: 'my-child-window-preload-script.js'
}
}
}
}
return { action: 'deny' }
})
// renderer process (mainWindow)
const childWindow = window.open('', 'modal')
childWindow.document.write('<h1>Hello</h1>')