electron_笔记

这篇具有很好参考价值的文章主要介绍了electron_笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

创建你的第一个应用:

package.json:

{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "my demo",
  "main": "main.js",
  "scripts": {
    "dev": "electron .  --inspect=5858",
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make",
    "win": "electron-builder --win --x64"
  },
  "author": "icestone",
  "license": "MIT",
  "devDependencies": {
    "@electron-forge/cli": "^6.1.1",
    "electron": "23.1.3",
    "electron-builder": "^23.6.0"
  },
  "win": {
    "icon": "icons/icon.ico",
    "target": [
      {
        "target": "nsis",
        "arch": [
          "x64",
          "ia32"
        ]
      }
    ]
  }
}

main.js

const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');

const createWindow = () => {
    const win = new BrowserWindow({
        width: 1000,
        height: 900,
        webPreferences: {
            preload: path.join(__dirname, './preload.js'),
        },
    })
    require('./src/js/menu'),
    ipcMain.handle('ping', () => 'pong');
    win.loadFile('index.html');
}


// 下面两种监听都可以
/*app.whenReady().then(() => {
    createWindow()
})*/
app.on('ready', () => {
    createWindow()
})

//  监听关闭时调用
app.on('window-all-closed', () => {
    console.log('close window')
    if (process.platform !== 'darwin') app.quit()
})

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
</p>
</body>
</html>

run:

electron_笔记

监听一个窗口的关闭:
    win.on('close',function () {
        console.log('window is close!')
    })

它的完整代码应该是:

const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');

const createWindow = () => {
    const win = new BrowserWindow({
        width: 1000,
        height: 900,
        webPreferences: {
            preload: path.join(__dirname, './preload.js'),
        },
    })
    ipcMain.handle('ping', () => 'pong');
    win.loadFile('index.html');
    win.on('close',function () {
        console.log('window is close!')
    })
}


// 下面两种监听都可以
/*app.whenReady().then(() => {
    createWindow()
})*/
app.on('ready', () => {
    createWindow()
})

//  监听关闭时调用
app.on('window-all-closed', () => {
    console.log('close window')
    if (process.platform !== 'darwin') app.quit()
})

electron的生命周期

生命周期事件:
  • ready

    • app初始化完成时调用一次
  • dom-ready

    • 一个窗口中的文本加载完成,此时可以执行dom操作
  • did-finsh-load

    • 导航完成时触发
  • window-all-closed

    • 所有窗口都被关闭时触发
  • before-quit

    • 在关闭窗口之前触发
  • will-quit

    • 在窗口关闭并且应用退出时触发
  • quit

    • 当所有窗口被关闭时触发
  • closed

    • 当所有窗口关闭时触发,此时应删除窗口引用

例如下面的main.js演示:

const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');

const createWindow = () => {
    const win = new BrowserWindow({
        width: 1000,
        height: 900,
        webPreferences: {
            preload: path.join(__dirname, './preload.js'),
        },
    })
    ipcMain.handle('ping', () => 'pong');
    win.loadFile('index.html');

    win.webContents.on('did-finish-load', () => {
        console.log('did-finish-load');
    })
    win.webContents.on('dom-ready', () => {
        console.log('dom-ready');
    })

    win.on('close', function () {
        console.log('close')
    })
}


// 下面两种监听都可以
/*app.whenReady().then(() => {
    createWindow()
})*/
app.on('ready', () => {
    console.log('ready')
    createWindow()
});
//  监听关闭时调用
app.on('window-all-closed', () => {
    console.log('all close window')
    if (process.platform !== 'darwin') app.quit()
});
app.on('before-quit', function () {
    console.log('before-quit')
});
app.on('will-quit', function () {
    console.log('will-quit');
});
app.on('quit', function () {
    console.log('quit');
});

run:

electron_笔记

窗口尺寸设置

使用nodemon

package.json中的script:

  "scripts": {
    "dev": "electron .  --inspect=5858",
    "start": "electron .",
    "nodemon": "nodemon --main.js --exec npm run dev"
  },

这样就可以使用nodemon监听main.js的改动了

相关属性

每次打开窗口默认会在屏幕的中央进行显示,如果想要更改,可以在mian.js中使用x,y来更改:

const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');

const createWindow = () => {
    const win = new BrowserWindow({
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        webPreferences: {
            preload: path.join(__dirname, './preload.js'),
        },
    })
    ipcMain.handle('ping', () => 'pong');
    win.loadFile('index.html');

    win.webContents.on('did-finish-load', () => {
        console.log('did-finish-load');
    })
    win.webContents.on('dom-ready', () => {
        console.log('dom-ready');
    })

    win.on('close', function () {
        console.log('close')
    })
}

// 下面两种监听都可以
/*app.whenReady().then(() => {
    createWindow()
})*/
app.on('ready', () => {
    console.log('ready')
    createWindow()
});
//  监听关闭时调用
app.on('window-all-closed', () => {
    console.log('all close window')
    if (process.platform !== 'darwin') app.quit()
});
app.on('before-quit', function () {
    console.log('before-quit')
});
app.on('will-quit', function () {
    console.log('will-quit');
});
app.on('quit', function () {
    console.log('quit');
});

然后他就更改了:

electron_笔记

但是此时,可能会先出现窗口,白屏一瞬间之后再加载内容,那么此时就可以使用:show: false设置一下

const win = new BrowserWindow({
        show: false,
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        webPreferences: {
            preload: path.join(__dirname, './preload.js'),
        },
    })
    win.on("ready-to-show", function () {
        win.loadFile('index.html');
    })

这里监听了ready-to-show,在这个阶段才调用加载index.html

设置最大,最小尺寸
const win = new BrowserWindow({
        show: false,
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        maxHeight: 1000,
        maxWidth: 1100,
        minHeight: 500,
        minWidth: 1000
    })
固定尺寸

使用resizable:false:

const win = new BrowserWindow({
        show: false,
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        maxHeight: 1000,
        maxWidth: 1100,
        minHeight: 500,
        minWidth: 1000,
        resizable:false
    })
main设置界面内容
设置title
const win = new BrowserWindow({
        // show: false,
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        // 设置最大尺寸
        maxHeight: 1000,
        maxWidth: 1100,
        // 设置最小尺寸
        minHeight: 500,
        minWidth: 1000,
        // 禁止缩放窗口
        // resizable:false
        title:'在main.js中设置的title'
    })
  • 注意,此时在index.html的title应该为空
设置icon
const win = new BrowserWindow({
        // show: false,
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        // 设置最大尺寸
        maxHeight: 1000,
        maxWidth: 1100,
        // 设置最小尺寸
        minHeight: 500,
        minWidth: 1000,
        // 禁止缩放窗口
        // resizable:false
        title:'在main.js中设置的title',
        icon:'./lg.ico'
    })

如图:

electron_笔记

不显示默认的窗口和菜单

frame:false,默认为true

运行:

electron_笔记

那么此时窗口无法进行拖动

透明窗体

transparent: true

运行:

electron_笔记

隐藏menu
const win = new BrowserWindow({
        // show: false,
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        // 设置最大尺寸
        maxHeight: 1000,
        maxWidth: 1100,
        // 设置最小尺寸
        minHeight: 500,
        minWidth: 1000,
        // 禁止缩放窗口
        // resizable:false
        title: '在main.js中设置的title',
        icon: './lg.ico',
        // 不显示默认窗口和菜单
        // frame:false
        // 透明窗体
        // transparent: true
        // 隐藏menu
        autoHideMenuBar: true
    })
调试面板

ctrl+shift+i

允许渲染进程和nodejs交互

一般情况下,在index.html中引用的js文件是无法导入nodejs中的包的,例如下面的代码:

index.js:

const o = require('electron');

// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
    const oBtn = document.getElementById('btn')
    oBtn.addEventListener('click', () => {
    })
})

在第一行导入了包,那么在应用的控制台中:

electron_笔记

默认情况下是不允许渲染进程中的js直接和nodejs进行交互,那么在开发中想要和nodejs进行交互,可以在main.js中开启:

webPreferences: {
    nodeIntegration: true,
        contextIsolation
:
    false
}

完整的main.js:

const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');

const createWindow = () => {
    const win = new BrowserWindow({
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        title: '在main.js中设置的title',
        icon: './lg.ico',
        autoHideMenuBar: true,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })
    win.loadFile('index.html');
}

//  监听关闭时调用
app.on('window-all-closed', () => {
    console.log('all close window')
    if (process.platform !== 'darwin') app.quit()
});

然后就不会报错了

渲染进程中不可以使用主进程的一些对象

例如像下面,在渲染进程中使用了BrowserWindow,虽然可以导入,但是不被允许:

// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow} = require('electron');
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
    const oBtn = document.getElementById('btn')
    oBtn.addEventListener('click', () => {
        let indexMin = new BrowserWindow({
            width: 1000,
            height: 900
        })
        indexMin.loadFile('../views/list.html');
        indexMin.on("close", () => {
            indexMin = null;
        })
    })
})

报错:

index.js:8 Uncaught TypeError: BrowserWindow is not a constructor
    at HTMLButtonElement.<anonymous> (index.js:8:24)
使用remote让渲染进程使用BrowserWindow

main.js中的主要代码:

const remote = require("@electron/remote/main") //1
remote.initialize()//2
remote.enable(win.webContents)//3

mian.js的完整代码:

const {app, BrowserWindow} = require('electron');
const remote = require("@electron/remote/main") //1
remote.initialize()//2

const createWindow = () => {
    const win = new BrowserWindow({
        x: 200,
        y: 200,
        width: 1000,
        height: 900,
        title: '在main.js中设置的title',
        icon: './lg.ico',
        autoHideMenuBar: true,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        },
    })
    win.loadFile('index.html');
    remote.enable(win.webContents)//3
}

app.on('ready', () => {
    console.log('ready')
    createWindow()
});
//  监听关闭时调用
app.on('window-all-closed', () => {
    console.log('all close window')
    if (process.platform !== 'darwin') app.quit()
});

index.js:

// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow} = require("@electron/remote");
console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
    const oBtn = document.getElementById('btn')
    oBtn.addEventListener('click', () => {
        let indexMin = new BrowserWindow({
            width: 1000,
            height: 900
        })
        indexMin.loadFile('./src/views/list.html');
        indexMin.on("close", () => {
            indexMin = null;
        })
    })
})

要注意这里的引用:

const {BrowserWindow} = require("@electron/remote");

electron_笔记

自定义窗口的实现
最小化,最大化,关闭的实现:

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
    <!--    <link rel="stylesheet/less" type="text/less" href="./src/css/index.less"/>-->
    <link rel="stylesheet" type="text/css" href="./src/css/index.css"/>
</head>
<body>
<div class="container">
    <div class="header">
        <div class="btn">minWindow</div>
        <div class="btn">maxWindow</div>
        <div class="btn">close</div>
    </div>

</div>

<script src="./index.js"></script>

</body>
</html>

index.js:

// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow, ipcMain, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();

console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
    const btns = document.getElementsByClassName('btn')
    const close = btns[2];
    const maxWindow = btns[1];
    const minWindow = btns[0];

    close.addEventListener('click', () => {
        console.log('关闭')
        mainWin.close();
    })
    maxWindow.addEventListener('click', () => {
        console.log('最大化')
        /*        console.log('是否为最大化')
                console.log(mainWin.isMaximizable());*/
        if (!mainWin.isMaximized()) {
            mainWin.maximize()
        } else {
            console.log('恢复尺寸')
            // 让当前窗口回到原始状态
            mainWin.restore();
        }
    })
    minWindow.addEventListener('click', () => {
        console.log('最小化')
        if (!mainWin.isMinimized()) {
            mainWin.minimize()
        } else {
            mainWin.restore();
        }
    })
})
阻止窗口关闭

监听窗口关闭之前的状态:

index.js:

// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow, ipcMain, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();

console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
    window.onbeforeunload = function () {
        console.log('关闭窗口')
        return false;
    }

// 点击打开一个新窗口
    const btns = document.getElementsByClassName('btn')
    const close = btns[2];
    const maxWindow = btns[1];
    const minWindow = btns[0];

    close.addEventListener('click', () => {
        console.log('关闭')
        mainWin.close();
    })
    maxWindow.addEventListener('click', () => {
        console.log('最大化')
        /*console.log('是否为最大化')
                console.log(mainWin.isMaximizable());*/
        if (!mainWin.isMaximized()) {
            mainWin.maximize()
        } else {
            console.log('恢复尺寸')
            // 让当前窗口回到原始状态
            mainWin.restore();
        }
    })
    minWindow.addEventListener('click', () => {
        console.log('最小化')
        if (!mainWin.isMinimized()) {
            mainWin.minimize()
        } else {
            mainWin.restore();
        }
    })
})

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
    <link rel="stylesheet" type="text/css" href="./src/css/index.css"/>
</head>
<body>
<div class="container">
    <div class="header">
        <div class="btn">minWindow</div>
        <div class="btn">maxWindow</div>
        <div class="btn">close</div>
    </div>

</div>
<div class="alert">
    确认关闭?
    <button class="close">yes!</button>
    <button class="notClose">no!</button>
</div>
<script src="./index.js"></script>
</body>
</html>

这里主要是index.js中的:

    window.onbeforeunload = function () {
    console.log('关闭窗口')
    return false;
}
弹窗控制窗口关闭与否:

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
    <link rel="stylesheet" type="text/css" href="./src/css/index.css"/>
</head>
<body>
<div class="container">
    <div class="header">
        <div class="btn">minWindow</div>
        <div class="btn">maxWindow</div>
        <div class="btn">close</div>
    </div>
</div>
<div class="alert">
    确认关闭?
    <button class="close">yes!</button>
    <button class="notClose">no!</button>
</div>
<script src="./index.js"></script>
</body>
</html>

index.css:

.container {
    display: flex;
    flex-direction: column;
}

.header {
    display: flex;
    width: 100%;
    flex-direction: row;
    justify-content: end;
    background: #8c8c73;
}

.header div {
    padding-right: 20px;
}

body {
    background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
}

.alert {
    display: none;
}

index.js:

// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow, ipcMain, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();

console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
    window.onbeforeunload = function () {
        console.log('关闭窗口')
        const alert = document.getElementsByClassName('alert')[0];
        alert.style.display = 'flex';
        const yesBtn = document.getElementsByClassName('close')[0];
        const noBtn = document.getElementsByClassName('notClose')[0];
        yesBtn.addEventListener('click', () => {
            mainWin.destroy();
        })
        noBtn.addEventListener('click', () => {
            alert.style.display = 'none';
        })
        return false;
    }

// 点击打开一个新窗口
    const btns = document.getElementsByClassName('btn')
    const close = btns[2];
    const maxWindow = btns[1];
    const minWindow = btns[0];

    close.addEventListener('click', () => {
        console.log('关闭')
        mainWin.close();
    })
    maxWindow.addEventListener('click', () => {
        console.log('最大化')
        /*console.log('是否为最大化')
                console.log(mainWin.isMaximizable());*/
        if (!mainWin.isMaximized()) {
            mainWin.maximize()
        } else {
            console.log('恢复尺寸')
            // 让当前窗口回到原始状态
            mainWin.restore();
        }
    })
    minWindow.addEventListener('click', () => {
        console.log('最小化')
        if (!mainWin.isMinimized()) {
            mainWin.minimize()
        } else {
            mainWin.restore();
        }
    })
})

main.js:

const {app, BrowserWindow} = require('electron')
const path = require('path')
const remote = require("@electron/remote/main") //1
remote.initialize()//2
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        frame: false,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })
    win.loadFile('index.html')
    win.on('close', function () {
        console.log('close')
    })
    remote.enable(win.webContents)//3
}
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})
父子及模态窗口

一般情况下创建的子窗口,在操作子窗口时,父窗口依旧可以操作:

main.js:

const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()

const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '子窗口及模态窗口',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })

    // 加载 index.html
    win.loadFile('index.html')
    //3
    remote.enable(win.webContents)

    // 打开开发工具
    // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        // 在 macOS 系统内, 如果没有已开启的应用窗口
        // 点击托盘图标时通常会重新创建一个新窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

index.html:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
</head>
<body>

<div class="container">
    <button id="btn">新增窗口</button>

</div>
<script src="./index.js"></script>
</body>
</html>

index.js:

const {BrowserWindow, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
window.addEventListener('DOMContentLoaded', () => {
    const btn = document.getElementById("btn");
    btn.addEventListener('click', () => {
        let subWin = new BrowserWindow({
            parent: mainWin,
            width: 1000,
            height: 900
        })
        subWin.loadFile('sub.html')
        subWin.on('close', () => {
            subWin = null;
        })
    })
})

run:

electron_笔记

此时是可以拖动父窗口的

但是使用模态窗口就可以避免这个问题,

模态窗口

main.js:

const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()

const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '子窗口及模态窗口',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })

    // 加载 index.html
    win.loadFile('index.html')
    //3
    remote.enable(win.webContents)

    // 打开开发工具
    // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        // 在 macOS 系统内, 如果没有已开启的应用窗口
        // 点击托盘图标时通常会重新创建一个新窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

index.html:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
</head>
<body>

<div class="container">
    <button id="btn">新增窗口</button>

</div>
<script src="./index.js"></script>
</body>
</html>

index.js:

const {BrowserWindow, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
window.addEventListener('DOMContentLoaded', () => {

    const btn = document.getElementById("btn");
    btn.addEventListener('click', () => {
        let subWin = new BrowserWindow({
            parent: mainWin,
            width: 1000,
            height: 900,
            modal: true
        })
        subWin.loadFile('sub.html')
        subWin.on('close', () => {
            subWin = null;
        })
    })
})

run:

electron_笔记

注意,这里主要起作用的是index.js的:

modal: true
自定义菜单
自定义一个简单的菜单
const {app, BrowserWindow, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '自定义菜单',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })
    // 1.定义自己需要的菜单
    let menuMap = [
        {label: '文件'},
        {label: '编辑'},
    ];
    // 2.利用上面的模板构建菜单项:
    let menu = Menu.buildFromTemplate(menuMap);
    // 3.将上述的自定义菜单添加到应用
    Menu.setApplicationMenu(menu);
    win.loadFile('index.html')
    //3
    remote.enable(win.webContents)
}
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

主要分三步:

  • 定义你的菜单,数组,需要在之前引入Menu:const {app, BrowserWindow, Menu} = require('electron')
// 1.定义自己需要的菜单
let menuMap = [
    {label: '文件'},
    {label: '编辑'},
];
  • 利用上面的模板构建菜单项:
let menu = Menu.buildFromTemplate(menuMap);
  • 将上述的自定义菜单添加到应用
// 3.将上述的自定义菜单添加到应用
Menu.setApplicationMenu(menu);
win.loadFile('index.html')
菜单的点击以及二级菜单
const {app, BrowserWindow, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '自定义菜单',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })
    // 1.定义自己需要的菜单
    let menuMap = [
        {
            label: '文件',
            submenu: [
                {
                    label: '打开文件夹',
                    click() {
                        console.log('open someone dir')
                    }
                },
                {
                    label: '打开文件'
                },
                {
                    label: '关于',
                    role: 'about'
                }
            ]
        },
        {label: '编辑'},
    ];
    // 2.利用上面的模板构建菜单项:
    let menu = Menu.buildFromTemplate(menuMap);
    // 3.将上述的自定义菜单添加到应用
    Menu.setApplicationMenu(menu);
    // 加载 index.html
    win.loadFile('index.html')
    //3
    remote.enable(win.webContents)
}
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

这里主要是menuMap发生变化,里面存储的click函数,在文件中定义的有其他的二级菜单

定义菜单之间的分割线
let menuMap = [
    {
        label: '文件',
        submenu: [
            {
                label: '打开文件夹',
                click() {
                    console.log('open someone dir')
                }
            },
            // 分割线
            {
                type: 'separator'
            },
            {
                label: '打开文件',
            },
            {
                label: '关于',
                role: 'about'
            }
        ]
    },
    {label: '编辑'},
];

例如上面的,传入type`的值表示不同的分割线

角色菜单以及类型
菜单中的内置角色
let menuMap = [
    {
        label: '内置角色',
        submenu: [
            {
                label: '复制',
                role: 'copy'
            },
            {
                label: '剪贴',
                role: 'cut'
            },
            {
                label: '粘贴',
                role: 'paste'
            },
            {
                label: '最小化',
                role: 'minimize'
            }
        ]
    }];
菜单中的选项卡:
let menuMap = [
    {
        label: '类型',
        submenu: [
            {
                label: '选项1',
                type: 'checkbox'
            },
            {
                label: '选项2',
                type: 'checkbox'
            },
            {
                label: '选项3',
                type: 'checkbox'
            },
            {
                type: 'separator'
            },
            {
                label: 'item1',
                type: 'radio'
            },
            {
                label: 'item2',
                type: 'radio'
            },
            {
                type: 'separator'
            },
            {
                label: 'windows',
                type: 'submenu',
                role: 'windowMenu'
            }
        ]
    }]
快捷键
let menuMap = [
    {
        label: '其他',
        submenu: [
            {
                label: '打开',
                icon: './open.png',
                accelerator: 'ctrl+o',
                click() {
                    console.log('open操作执行了!')
                }
            },
        ]
    }
]

electron_笔记
electron_笔记
electron_笔记

动态创建菜单

main.js:

const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()

const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: 'demo页面',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })

    // 加载 index.html
    win.loadFile('index.html')
    //3
    remote.enable(win.webContents)

    // 打开开发工具
    // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        // 在 macOS 系统内, 如果没有已开启的应用窗口
        // 点击托盘图标时通常会重新创建一个新窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
</head>
<body>
<h1>自定义菜单</h1>
<div class="container">
    <button id="add">创建自定义菜单</button>
    <input type="text" value="输入自定义菜单项内容" id="menuVal">
    <button id="addMenu">添加菜单项</button>

</div>
<script src="./index.js"></script>
</body>
</html>

index.js:

const {BrowserWindow, Menu, MenuItem} = require("@electron/remote");

console.log('当前路径')
console.log(__dirname)
// 自定义全局变量
let menuItem = new Menu();

window.addEventListener('DOMContentLoaded', () => {
    let addBtn = document.getElementById('add');
    let addMenuBtn = document.getElementById('addMenu');
    let input = document.getElementById('menuVal');

// 生成自定义的菜单:
    addBtn.addEventListener('click', () => {
// 创建菜单
        let menuFile = new MenuItem({label: '文件', type: 'normal'});
        let menuEdit = new MenuItem({label: '编辑', type: 'normal'});
        let customMenu = new MenuItem({label: '自定义菜单', submenu: menuItem});
// 将创建好的菜单添加至menu
        let menu = new Menu();
        menu.append(menuFile)
        menu.append(menuEdit)
        menu.append(customMenu)
// 将menu放置于app中显示
        Menu.setApplicationMenu(menu);
    })

    addMenuBtn.addEventListener('click', () => {
        // 获取当前input输入框的内容
        const con = input.value.trim();
        if (con) {
            menuItem.append(new MenuItem({
                label: con, type: 'normal'
            }))
            input.value = '';
        }
    })
})

运行:

electron_笔记

右键菜单

mian.js:

const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()

const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '右键菜单',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })

    // 加载 index.html
    win.loadFile('index.html')
    //3
    remote.enable(win.webContents)

    // 打开开发工具
    // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        // 在 macOS 系统内, 如果没有已开启的应用窗口
        // 点击托盘图标时通常会重新创建一个新窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
</head>
<body>
<h1>你好!</h1>
<div class="container">

</div>
<script src="./index.js"></script>
</body>
</html>

index.js:

const {Menu, getCurrentWindow} = require("@electron/remote");
const remote = require("@electron/remote/main")
let mainWin = getCurrentWindow();


// 创建一个自定义的菜单内容
let contextTemp = [
    {label: 'Run Code'},
    {label: '转到定义'},
    {type: 'separator'},
    {
        label: '其他功能',
        click() {
            console.log('其他功能被点击了')
        }
    },
]
// 依据上面模板来创建menu
let menu = Menu.buildFromTemplate(contextTemp);

// 在鼠标右击行为后显示出来
window.addEventListener('DOMContentLoaded', () => {
// 监听右击
    window.addEventListener('contextmenu', (ev) => {
        ev.preventDefault();
        menu.popup({
            window: mainWin
        })
    }, false)
})

运行:
electron_笔记

主进程与渲染进程之间通讯

监听页面元素点击,渲染进程向主进程发消息:

渲染进程向主进程发送消息

index.html

<button id="one">渲染到主异步操作</button>
    <br>
    <button id="two">渲染到主同步操作</button>

index.js

const {
    ipcRenderer
} = require('electron')

window.onload = function () {
    const aBtn = document.getElementById('one');
    const twoBtn = document.getElementById('two');
// 异步发送消息
// 通过异步api在渲染进程中给主进程发送消息
    aBtn.addEventListener('click', () => {
        ipcRenderer.send('msg1', '来自渲染进程的异步消息');
    })
// 接收来自主进程的异步消息
    ipcRenderer.on('msg1Re', (ev, data) => {
        console.log('来自主进程的data:')
        console.log(data)
    })
// 同步发送消息
    twoBtn.addEventListener('click', () => {
        let val = ipcRenderer.sendSync('msg2', '同步消息')
        console.log("val:")
        console.log(val)
    })
}

main.js

const {app, BrowserWindow, ipcMain, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()

let temp = [
    {
        label: 'send',
        click() {
            BrowserWindow.getFocusedWindow().webContents.send('mtp','来自于主进程的消息')
        }
    }
]
let menu = Menu.buildFromTemplate(temp);
Menu.setApplicationMenu(menu);

const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '主进程与渲染进程之间通讯',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })

    // 加载 index.html
    win.loadFile('index.html')
    win.webContents.openDevTools();
    //3
    remote.enable(win.webContents)

    // 打开开发工具
    // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        // 在 macOS 系统内, 如果没有已开启的应用窗口
        // 点击托盘图标时通常会重新创建一个新窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

// 主进程接受消息
ipcMain.on('msg1', (ev, data) => {
    console.log('data:')
    console.log(data)
// 给渲染进程发送消息
    ev.sender.send('msg1Re', '这是一条来自主进程的异步消息')
})
ipcMain.on('msg2', (ev, data) => {
    console.log(data)
    ev.returnValue = '来自于主进程的同步消息'
})

上面代码中主要是ipcMain.on来接收渲染进程发送来的消息

主进程接收消息后向渲染进程发送消息

主进程可以这样接收并返回:

ipcMain.on('msg1', (ev, data) => {
    console.log('data:')
    console.log(data)
	// 给渲染进程发送消息
    ev.sender.send('msg1Re', '这是一条来自主进程的异步消息')
})
ipcMain.on('msg2', (ev, data) => {
    console.log(data)
    // 给渲染进程发送消息
    ev.returnValue = '来自于主进程的同步消息'
})

渲染进程的接收:

 ipcRenderer.on('msg1Re', (ev, data) => {
        console.log('来自主进程的data:')
        console.log(data)
    })
// 同步发送消息
    twoBtn.addEventListener('click', () => {
        let val = ipcRenderer.sendSync('msg2', '同步消息')
        console.log("val:")
        console.log(val)
    })

上面的代码中,渲染进程向主进程发送消息,并接收

主线程向渲染进程发送消息

主线程:

let temp = [
    {
        label: 'send',
        click() {
            BrowserWindow.getFocusedWindow().webContents.send('mtp','来自于主进程的消息')
        }
    }
]
let menu = Menu.buildFromTemplate(temp);
Menu.setApplicationMenu(menu);

上面的代码中,设置了一个点击事件,点击触发向当前获取焦点的窗口发送消息

渲染进程:

    ipcRenderer.on('mtp', (ev, data) => {
        console.log(data)
    })

完成代码:

main.js

const {app, BrowserWindow, ipcMain, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()

let temp = [
    {
        label: 'send',
        click() {
            BrowserWindow.getFocusedWindow().webContents.send('mtp','来自于主进程的消息')
        }
    }
]
let menu = Menu.buildFromTemplate(temp);
Menu.setApplicationMenu(menu);

const createWindow = () => {
    // 创建浏览窗口
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        title: '主进程与渲染进程之间通讯',
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    })

    // 加载 index.html
    win.loadFile('index.html')
    win.webContents.openDevTools();
    //3
    remote.enable(win.webContents)

    // 打开开发工具
    // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        // 在 macOS 系统内, 如果没有已开启的应用窗口
        // 点击托盘图标时通常会重新创建一个新窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

// 主进程接受消息
ipcMain.on('msg1', (ev, data) => {
    console.log('data:')
    console.log(data)
// 给渲染进程发送消息
    ev.sender.send('msg1Re', '这是一条来自主进程的异步消息')
})
ipcMain.on('msg2', (ev, data) => {
    console.log(data)
    ev.returnValue = '来自于主进程的同步消息'
})

index.js

const {
    ipcRenderer
} = require('electron')

window.onload = function () {
    const aBtn = document.getElementById('one');
    const twoBtn = document.getElementById('two');
// 异步发送消息
// 通过异步api在渲染进程中给主进程发送消息
    aBtn.addEventListener('click', () => {
        ipcRenderer.send('msg1', '来自渲染进程的异步消息');
    })
// 接收来自主进程的异步消息
    ipcRenderer.on('msg1Re', (ev, data) => {
        console.log('来自主进程的data:')
        console.log(data)
    })
// 同步发送消息
    twoBtn.addEventListener('click', () => {
        let val = ipcRenderer.sendSync('msg2', '同步消息')
        console.log("val:")
        console.log(val)
    })
    ipcRenderer.on('mtp', (ev, data) => {
        console.log(data)
    })
}

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title></title>
</head>
<body>
<h1>渲染进程与主进程通信</h1>
<div class="container">
    <button id="one">渲染到主异步操作</button>
    <br>
    <button id="two">渲染到主同步操作</button>
</div>
<script src="./index.js"></script>
</body>
</html>
基于本地存储的渲染进程通信

文章来源地址https://www.toymoban.com/news/detail-421870.html

到了这里,关于electron_笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Web3 系列开发教程——创建你的第一个 NFT(7)】创建一个 NFT DApp,给你的 NFT 赋予属性,例如图片

    在本文中,你将构建一个 NFT 铸币机,并学习如何通过使用 Metamask 和 Web3 工具将你的智能合约连接到 React 前端,来创建一个NFT dApp。 我认为,对于具备 Web2 开发背景的开发者来说,最大的挑战之一是 弄清楚如何将你的智能合约连接到前端项目并与之交互。 通过构建 NFT 铸币

    2024年01月16日
    浏览(63)
  • C++QT教程3——手册4.11.1自带教程(笔记)——创建一个基于Qt Widget的应用程序

    本教程介绍如何使用Qt Creator创建一个小型Qt应用程序,名为Text Finder。它是Qt UI工具中Text Finder示例的简化版本。应用程序的用户界面是使用Qt Designer通过Qt小部件构建的。应用程序逻辑是通过使用代码编辑器编写的C++代码。 选择文件 新建文件或项目 应用程序 Qt Widgets应用程序

    2024年02月13日
    浏览(48)
  • Kibana:创建你的第一个仪表板

    了解从你自己的数据创建仪表板的最常用方法。 本教程将从分析师查看网站日志的角度使用示例数据,但这种类型的仪表板适用于任何类型的数据。 完成后,你将全面了解示例 Web 日志数据。 在本次的展示中,我将使用最新的 Elastic Stack 8.7.1 来进行展示。 Kibana:创建你的第

    2024年02月06日
    浏览(83)
  • Django 初级指南:创建你的第一个 Django 项目

    Django 是一个强大的 Python Web 框架,它采用了“模型-视图-控制器”(MVC)的设计模式,能够帮助开发者快速、简洁地创建高质量的 Web 应用。这篇文章将引导你创建你的第一个 Django 项目。 首先,你需要在你的 Python 环境中安装 Django。你可以使用 pip 包管理器来安装: 你可以

    2024年02月13日
    浏览(67)
  • 【Three.js基础入门】:创建你的第一个3D场景

    Three.js是一种强大的JavaScript库,用于在Web浏览器中创建交互式的3D图形和动画。无需熟练的图形编程经验,你也可以通过Three.js轻松地构建令人惊叹的3D场景。 本文将带你逐步学习如何入门Three.js,从创建一个简单的3D场景开始。 我们将介绍如何使用Three.js创建你的第一个3D场景

    2024年02月16日
    浏览(138)
  • 【Web3 系列开发教程——创建你的第一个 NFT(3)】开始创建 NFT

    本文将引导你使用以太坊和星际文件系统 (IPFS) 编写和部署不可替代 (ERC721) 代币智能合约。 星际文件系统 IPFS 是一个旨在 实现文件的分布式存储、共享和持久化的网络传输协议 。它是一种内容可寻址的对等超媒体分发协议。在IPFS网络中的节点构成一个分布式文件系统。它是

    2023年04月08日
    浏览(65)
  • Dynamics 365 Finance and Operations 创建你的第一个项目框架

    第一章:浅谈Dynamics CRM开发转Dynamics AX开发的感受与差异 第二章:Dynamics 365 Finance and Operations 虚拟机安装及使用 第三章:Dynamics 365 Finance and Operations 创建你的第一个项目(Visual Studio) 本文为大家介绍如何在Visual Studio中创建Model和Solution。并且让你了解Model和solution的基本概念

    2024年02月06日
    浏览(48)
  • 构建你的第一个Android应用

    一、Android的核心组件 Android是一种基于Linux的开源操作系统,主要用于移动设备,如智能手机和平板电脑。Android的设计目标是为用户提供一个统一、灵活和丰富的用户体验,同时保持开放性和兼容性。 Android的核心组件 包括: 应用程序框架:提供了一套用于开发和运行应用程

    2024年02月01日
    浏览(51)
  • eletron+react+antd+node开发桌面小程序并打包(electron-packager+electron-builder)

    首先罗列一下项目中用到的技术: electron, react,antd, typescript, node,及打包命令:pkg,electron-packager,electron-builder及child_process实现多进程 需求:开发一个桌面应用,左侧展示视频(需要用到node服务进行rtsp转码),右侧一些获取视频流需要的表单数据。 因为从需求到完成小

    2024年02月11日
    浏览(41)
  • Django(2)-编写你的第一个 Django 应用

    本教程的目的是创建一个网络投票应用程序。 它将由两部分组成: 一个让人们查看和投票的公共站点。 一个让你能添加、修改和删除投票的管理站点。 每一个应用是一个python包,一个项目可以包含多个应用。 可以看到生成了一个polls文件夹,包含如下文件 polls/views polls/u

    2024年02月11日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包