• Electron常用API window.open及父子窗口和模态窗口


    window.open

    打开一个新窗口并加载 URL。

    当调用 window.open 以在网页中创建新窗口时,将为url 创建一个新的BrowserWindow 实例,并返回一个代理至 window.open 以让页面对其进行有限的控制。 

    window.open(url,frameName,features)

    • url String
    • frameName 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 String
    • targetOrigin String

    将消息发送给指定来源的父窗口,如果未指定来源则发送给*,即所有窗口。

    使用 Chrome 的 window.open()

    如果要使用 Chrome 的内置 window.open(),请在 webPreferences 选项中将 nativeWindowOpen 设置为 true。

    原生 window.open () 允许同步打开窗口, 因此可以方便的选择是对话框还是首选项窗口。

    该选项也可以设置在标签上:

    "nativeWindowOpen=yes">

    BrowserWindow的创建可通过WebContents 的 new-window事件进行定制 。

    1. // main process
    2. const mainWindow = new BrowserWindow({
    3. width: 800,
    4. height: 600,
    5. webPreferences: {
    6. nativeWindowOpen: true
    7. }
    8. })
    9. mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
    10. if (frameName === 'modal') {
    11. // open window as modal
    12. event.preventDefault()
    13. Object.assign(options, {
    14. modal: true,
    15. parent: mainWindow,
    16. width: 100,
    17. height: 100
    18. })
    19. event.newGuest = new BrowserWindow(options)
    20. }
    21. })
    22. // renderer process (mainWindow)
    23. const modal = window.open('', 'modal')
    24. modal.document.write('

      Hello

      '
      )

    例: 打开一个子窗口并向父窗口传递消息

    主线程脚本

    main.js

    1. //为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
    2. const { app, BrowserWindow } = require('electron')
    3. //在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
    4. function createWindow () {
    5. const win = new BrowserWindow({
    6. width: 800,
    7. height: 600,
    8. webPreferences: {
    9. //开启webview 标签 Electron >= 5 后需要开启
    10. webviewTag:true,
    11. nodeIntegration: true
    12. }
    13. })
    14. win.loadFile('index.html')
    15. }
    16. //你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
    17. app.whenReady().then(createWindow)
    18. //您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的
    19. app.on('window-all-closed', () => {
    20. if (process.platform !== 'darwin') {
    21. app.quit()
    22. }
    23. })
    24. //您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序
    25. app.on('activate', () => {
    26. if (BrowserWindow.getAllWindows().length === 0) {
    27. createWindow()
    28. }
    29. })

    主窗口

    index.html

    1. DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Hello World!title>
    6. <style>
    7. .for_file_drag{
    8. width: 100%;
    9. height: 400px;
    10. background-color: pink;
    11. }
    12. style>
    13. head>
    14. <body>
    15. <h1>window open 函数h1>
    16. <button onclick="openChildWindow()">点击弹出子窗口button>
    17. body>
    18. <script>
    19. //打开当前目录child.html 为子窗口
    20. function openChildWindow() {
    21. window.open('child.html', '_blank')
    22. }
    23. //添加消息监听
    24. window.addEventListener('message', (e) => {
    25. console.log('接受到的消息:'+ e.data);
    26. });
    27. script>
    28. html>

    子窗口

    child.html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>子窗口title>
    6. head>
    7. <body>
    8. <h1>这是子窗口h1>
    9. <button onclick="sendParentMsg()">向父窗口回传信息button>
    10. body>
    11. <script>
    12. function sendParentMsg() {
    13. window.opener.postMessage('test');
    14. }
    15. script>
    16. html>

    效果

    例:打开子窗口的另一种方式

    main.js

    1. const { app, BrowserWindow } = require('electron')
    2. function createWindow() {
    3. const win = new BrowserWindow({
    4. width: 800,
    5. height: 600,
    6. show: false,
    7. // frame: true,
    8. // autoHideMenuBar: true,
    9. title: "Samve",
    10. // icon: "",
    11. webPreferences: {
    12. nodeIntegration: true,
    13. contextIsolation: false,
    14. enableRemoteModule: true
    15. }
    16. })
    17. require('@electron/remote/main').initialize()
    18. require("@electron/remote/main").enable(win.webContents)
    19. win.loadFile('index.html')
    20. win.on("ready-to-show", function(){
    21. win.show();
    22. })
    23. }
    24. app.on("ready", function(){
    25. createWindow();
    26. })
    27. app.on("window-all-closed", function(){
    28. app.quit();
    29. })

     index.html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <h1>父窗口h1>
    9. <div><button id="btn">打开button>div>
    10. <script src="render.js">script>
    11. body>
    12. html>

    render.js

    1. const remote = require("@electron/remote")
    2. window.addEventListener("DOMContentLoaded", () => {
    3. const oBtn = document.getElementById("btn");
    4. oBtn.addEventListener("click", () => {
    5. let subWin = new remote.BrowserWindow({
    6. parent: remote.getCurrentWindow(),
    7. width: 500,
    8. height: 300
    9. })
    10. console.log("loadFile");
    11. subWin.loadFile("sub.html");
    12. subWin.on("close", () => {
    13. subWin = null;
    14. })
    15. })
    16. })

     sub.html

    1. DOCTYPE html>
    2. Document
    3. 子页面

    例:在父窗口中控制关闭子窗口

    在第一个例子中演示打开窗口并回传信息,那如果要在主窗口中关闭子窗口怎么做呢?这时候就要用

    BowserWindowProxy对象了

    Returns BrowserWindowProxy - 创建一个新窗口,并返回一个 BrowserWindowProxy 类的实例。

     这个对象是创建新窗口返回的

    api参考:

    https://www.electronjs.org/docs/api/browser-window-proxy

    将上面的主窗口代码稍微改下

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Hello World!title>
    6. <style>
    7. .for_file_drag{
    8. width: 100%;
    9. height: 400px;
    10. background-color: pink;
    11. }
    12. style>
    13. head>
    14. <body>
    15. <h1>window open 函数h1>
    16. <button onclick="openChildWindow()">点击弹出子窗口button>
    17. <button onclick="closeChildWindow()">点击关闭子窗口button>
    18. body>
    19. <script>
    20. let childBowserWindowProxy = null;
    21. //打开当前目录child.html 为子窗口
    22. function openChildWindow() {
    23. childBowserWindowProxy = window.open('child.html', '_blank')
    24. }
    25. //关闭当前窗口
    26. function closeChildWindow(){
    27. childBowserWindowProxy.close();
    28. }
    29. //添加消息监听
    30. window.addEventListener('message', (e) => {
    31. console.log('接受到的消息:'+ e.data);
    32. });
    33. script>
    34. html>

    关于window open函数的疑问

    在第二例子中,我发现不管我点击几次弹出子窗口,app只会弹出一个子窗口,这是为什么呢?

    经过一阵研究发现,只要window.open 的第二个参数也就是frameName参数一致,它就会始终只有一个

    例如这种只会有一个

    1. //打开当前目录child.html 为子窗口
    2. function openChildWindow() {
    3. childBowserWindowProxy = window.open('child.html', '_blank')
    4. }

     但是这种会点击几个创建几个

    1. //打开当前目录child.html 为子窗口
    2. function openChildWindow() {
    3. childBowserWindowProxy = window.open('child.html', '_blank'+ new Date().getTime())
    4. }

    父子窗口

    父子窗口(Mac OS X和Windows有一定差异)

    • 1、子窗口总是在父窗口之上 
    • 2、如果父窗口关闭,子窗口自动关闭

    子窗口相当于父窗口的悬浮窗口

    Mac OS X和Windows的父子窗口的区别是:

    • 在Mac OS X下,移动父窗口,子窗口会随着父窗口移动
    • 在Windows下子窗口不会移动

    main.js

    1. /**
    2. * 父子窗口(Mac OS X和Windows有一定差异)
    3. * 1、子窗口总是在父窗口之上
    4. * 2、如果父窗口关闭,子窗口自动关闭
    5. *
    6. * 子窗口相当于父窗口的悬浮窗口
    7. * Mac OS X和Windows的父子窗口的区别是:
    8. * 在Mac OS X下,移动父窗口,子窗口会随着父窗口移动
    9. * 在Windows下子窗口不会移动
    10. */
    11. const {
    12. app,
    13. BrowserWindow
    14. } = require('electron')
    15. function createWindow() {
    16. const win = new BrowserWindow({
    17. width: 800,
    18. height: 600,
    19. // frame: false,
    20. webPreferences: {
    21. // preload: path.join(__dirname, 'preload.js'),
    22. nodeIntegration: true,
    23. contextIsolation: false
    24. }
    25. })
    26. win.loadFile('index.html')
    27. childWin = new BrowserWindow({
    28. parent: win, width: 400, height: 300,
    29. //module:true
    30. });
    31. childWin.loadFile('child.html');
    32. }
    33. app.whenReady().then(() => {
    34. createWindow()
    35. app.on('activate', () => {
    36. if (BrowserWindow.getAllWindows().length === 0) {
    37. createWindow()
    38. }
    39. })
    40. })
    41. app.on('window-all-closed', () => {
    42. if (process.platform !== 'darwin') {
    43. app.quit()
    44. }
    45. })

    index.html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Hello World!title>
    6. <style>
    7. .for_file_drag{
    8. width: 100%;
    9. height: 400px;
    10. background-color: pink;
    11. }
    12. style>
    13. head>
    14. <body>
    15. <h1>父窗口h1>
    16. body>
    17. html>

     child.html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>子窗口title>
    6. head>
    7. <body>
    8. <h1>这是子窗口h1>
    9. body>
    10. html>

    模态窗口(Mac OS X和Windows差异比较大)

    模态窗口是指禁用父窗口的子窗口,也就是说,处于模态的子窗口显示后,无法使用父窗口,直到子窗口关闭。

    1、模态窗口需要是另外一个窗口;
    2、一旦模态窗口显示,父窗口将无法使用。

    modal=true

    Mac OS X 和Windows的模态窗口差异:

    1、模态窗口在Mac OS X下会隐藏的标题栏,只能通过close方法关闭模态子窗口

     在Windows下,模态子窗口仍然会显示菜单和标题栏

    2、在Mac OS X下,模态子窗口显示后,父窗口仍然可以拖动,但无法关闭,在Windows下,模态子窗口显示后父窗口无法拖动

    应用:主要用于桌面应用的对话框显示,如设置对话框、打开对话框。

    代码示例,同父子窗口,只是子窗口多了一个modal属性,其值为true。

  • 相关阅读:
    LeetCode-1668. 最大重复子字符串【字符串匹配】
    Redis
    Linux的关机和重启
    Vite知识体系简述
    大数据学习的一些概念(值得背)
    (高阶) Redis 7 第16讲 预热/雪崩/击穿/穿透 缓存篇
    thinkPHP框架详解+部署
    重写 HttpServletRequestWrapper
    游戏服务器该如何选择
    虚拟人产业面临的挑战
  • 原文地址:https://blog.csdn.net/duansamve/article/details/126671749