Electron window.open 函数 和 Browser-window-proxy 对象的使用
官方文档:
https://www.electronjs.org/docs/api/window-open
https://www.electronjs.org/docs/api/browser-window-proxy
window.open 函数
打开一个新窗口并加载 URL。
当调用 window.open
以在网页中创建新窗口时,将为url
创建一个新的BrowserWindow 实例,并返回一个代理至 window.open
以让页面对其进行有限的控制。
The proxy has limited standard functionality implemented to be compatible with traditional web pages. For full control of the new window you should create a BrowserWindow
directly.
The newly created BrowserWindow
will inherit the parent window's options by default. To override inherited options you can set them in the features
string.
window.open(url,frameName,features)
url
StringframeName
String(可选)features
String(可选)
Returns BrowserWindowProxy
- 创建一个新窗口,并返回一个 BrowserWindowProxy
类的实例。
features
字符串遵循标准浏览器的格式,但每个 feature 必须是BrowserWindow
选项中的字段。 These are the features you can set via features
string: zoomFactor
, nodeIntegration
, preload
, javascript
, contextIsolation
, webviewTag
.
例如:
window.open('https://github.com', '_blank', 'nodeIntegration=no')
注意:
- 如果在父窗口中禁用了 Node integration, 则在打开的
window
中将始终被禁用。 - 如果在父窗口中启用了上下文隔离, 则在打开的
window
中将始终被启用。 - 父窗口禁用 Javascript,打开的
window
中将被始终禁用 features
中给定的非标准特性 (不由 Chromium 或 Electron 处理) 将被传递到additionalFeatures
参数中的任何已注册webContent
的new-window
事件处理程序。
window.opener.postMessage(message, targetOrigin)
message
StringtargetOrigin
String
将消息发送给指定来源的父窗口,如果未指定来源则发送给*
,即所有窗口。
使用 Chrome 的 window.open()
如果要使用 Chrome 的内置 window.open()
,请在 webPreferences
选项中将 nativeWindowOpen
设置为 true
。
原生 window.open ()
允许同步打开窗口, 因此可以方便的选择是对话框还是首选项窗口。
该选项也可以设置在<webview>
标签上:
<webview webpreferences="nativeWindowOpen=yes"></webview>
BrowserWindow
的创建可通过WebContents
的 new-window
事件进行定制 。
// main process
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nativeWindowOpen: true
}
})
mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
if (frameName === 'modal') {
// open window as modal
event.preventDefault()
Object.assign(options, {
modal: true,
parent: mainWindow,
width: 100,
height: 100
})
event.newGuest = new BrowserWindow(options)
}
})
// renderer process (mainWindow)
const modal = window.open('', 'modal')
modal.document.write('<h1>Hello</h1>')
例: 打开一个子窗口并向父窗口传递消息
主线程脚本
main.js
//为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
const { app, BrowserWindow } = require('electron')
//在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//开启webview 标签 Electron >= 5 后需要开启
webviewTag:true,
nodeIntegration: true
}
})
win.loadFile('index.html')
}
//你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
app.whenReady().then(createWindow)
//您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
//您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
主窗口
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<style>
.for_file_drag{
width: 100%;
height: 400px;
background-color: pink;
}
</style>
</head>
<body>
<h1>window open 函数</h1>
<button onclick="openChildWindow()">点击弹出子窗口</button>
</body>
<script>
//打开当前目录child.html 为子窗口
function openChildWindow() {
window.open('child.html', '_blank')
}
//添加消息监听
window.addEventListener('message', (e) => {
console.log('接受到的消息:'+ e.data);
});
</script>
</html>
子窗口
child.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子窗口</title>
</head>
<body>
<h1>这是子窗口</h1>
<button onclick="sendParentMsg()">向父窗口回传信息</button>
</body>
<script>
function sendParentMsg() {
window.opener.postMessage('test');
}
</script>
</html>
效果
例:在父窗口中控制关闭子窗口
在第一个例子中演示打开窗口并回传信息,那如果要在主窗口中关闭子窗口怎么做呢?这时候就要用
BowserWindowProxy对象了
Returns
BrowserWindowProxy
- 创建一个新窗口,并返回一个BrowserWindowProxy
类的实例。
这个对象是创建新窗口返回的
api参考:
https://www.electronjs.org/docs/api/browser-window-proxy
将上面的主窗口代码稍微改下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<style>
.for_file_drag{
width: 100%;
height: 400px;
background-color: pink;
}
</style>
</head>
<body>
<h1>window open 函数</h1>
<button onclick="openChildWindow()">点击弹出子窗口</button>
<button onclick="closeChildWindow()">点击关闭子窗口</button>
</body>
<script>
let childBowserWindowProxy = null;
//打开当前目录child.html 为子窗口
function openChildWindow() {
childBowserWindowProxy = window.open('child.html', '_blank')
}
//关闭当前窗口
function closeChildWindow(){
childBowserWindowProxy.close();
}
//添加消息监听
window.addEventListener('message', (e) => {
console.log('接受到的消息:'+ e.data);
});
</script>
</html>
关于window open函数的疑问
在第二例子中,我发现不管我点击几次弹出子窗口,app只会弹出一个子窗口,这是为什么呢?
经过一阵研究发现,只要window.open
的第二个参数也就是frameName
参数一致,它就会始终只有一个
例如这种只会有一个
//打开当前目录child.html 为子窗口
function openChildWindow() {
childBowserWindowProxy = window.open('child.html', '_blank')
}
但是这种会点击几个创建几个
//打开当前目录child.html 为子窗口
function openChildWindow() {
childBowserWindowProxy = window.open('child.html', '_blank'+ new Date().getTime())
}