跳到主要内容

从渲染进程打开窗口

有几种方法可以控制如何在渲染器中从受信任或不受信任的内容创建窗口。窗口可以通过两种方式从渲染器创建

  • 点击带有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])

  • url 字符串
  • frameName 字符串(可选)
  • features 字符串(可选)

返回 Window | null

features 是一个逗号分隔的键值对列表,遵循浏览器的标准格式。Electron 将尽可能地从此列表中解析BrowserWindowConstructorOptions,以方便使用。为了完全控制和更好的可用性,请考虑使用webContents.setWindowOpenHandler来自定义 BrowserWindow 的创建。

可以从 features 字符串直接设置(未嵌套)一部分WebPreferenceszoomFactornodeIntegrationpreloadjavascriptcontextIsolationwebviewTag

例如

window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIntegration=no')

注意

  • 如果在父窗口中禁用了 Node 集成,则在打开的window中始终禁用 Node 集成。
  • 如果在父窗口中启用了上下文隔离,则在打开的window中始终启用上下文隔离。
  • 如果在父窗口中禁用了 JavaScript,则在打开的window中始终禁用 JavaScript。
  • features中给出的非标准功能(Chromium 或 Electron 未处理的功能)将传递给任何已注册的webContentsdid-create-window事件处理程序中的options参数。
  • frameName 遵循位于原生文档中的target的规范。
  • 打开about:blank时,子窗口的WebPreferences将从父窗口复制,并且无法覆盖它,因为 Chromium 在这种情况下会跳过浏览器端导航。

要自定义或取消窗口的创建,您可以选择使用主进程中的webContents.setWindowOpenHandler()设置覆盖处理程序。返回{ action: 'deny' }将取消窗口。返回{ action: 'allow', overrideBrowserWindowOptions: { ... } }将允许打开窗口并设置创建窗口时使用的BrowserWindowConstructorOptions。请注意,这比通过功能字符串传递选项更强大,因为渲染器在决定安全首选项方面的权限比主进程更有限。

除了传入actionoverrideBrowserWindowOptions之外,还可以像这样传入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>')