• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

electron入门(16.0版本亲测可用)

互联网 diligentman 2小时前 4次浏览

根据业务需求,开始学习electron跨桌面应用框架。

记录~~~~~

创建一个electron项目

在node环境的支持下,新建文件夹

npm init -y 	//创建一个基础package
npm i electron		
npm i electron/remote		//由于新版本,需要使用这个package来使用remote模块

这样子,一个基础目录就准备好了,接下来需要准备一个主进程js文件和html主进程界面,并在main.js中写入:

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

//主进程启动文件
app.on('ready',function(){
    const mainWindow = new BrowserWindow({
        height:500,
        width:800,
        webPreferences:{
            // 开启node
            nodeIntegration: true,
            contextIsolation: false,
            // 开启remote
            enableRemoteModule:true,
        }
    });
    //主进程关闭,退出
    mainWindow.on('close',() => {
		if (process.platform != 'darwin') {
	        app.quit();
	    }
	}
})

开启后效果如图所示:
electron入门(16.0版本亲测可用)
控制台是默认不显示的,通过以下命令可以开启当前进程的控制台:

mainWindow.webContents.openDevTools();

electron应用的热重载

每次修改完代码需要手动关闭再electron .很麻烦,可以通过安装electron-reloader包进行热重载,类似于webpack的devServer。

yarn add @electron-reloader		//安装

//在入口文件(主进程中)加入代码
try {
        require('electron-reloader')(module);
} catch (_) { }

remote创建渲染进程

可以通过remote模块实现主进程下的渲染进程创建,如点击主进程的某个button开启一个新的进程,因此需要一个渲染进程的对应html、js文件。

main.js

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

//主进程启动文件
app.on('ready',function(){
    const mainWindow = new BrowserWindow({
        height:500,
        width:800,
        webPreferences:{
            // 开启node
            nodeIntegration: true,
            contextIsolation: false,
            // 开启remote
            enableRemoteModule:true,
        }
    });
    
    //引入remote进程模块
    require('@electron/remote/main').initialize()
	require('@electron/remote/main').enable(mainWindow.webContents)
	mainWindow.webContents.openDevTools();
	
    //主进程关闭,退出
    mainWindow.on('close',() => {
		if (process.platform != 'darwin') {
	        app.quit();
	    }
	}
})

render.js

const {BrowserWindow} = require('@electron/remote')
const {ipcRenderer} = require('electron')
const open_new = document.querySelector('span');


window.onload = function(){
    open_new.onclick = ()=>{
        var newBroswer = new BrowserWindow({
            width:400,
            height:400,
            webPreferences:{
                // 开启node
                nodeIntegration: true,
                contextIsolation: false,
            }
        });
        newBroswer.loadFile('render.html')
        newBroswer.webContents.openDevTools();
        newBroswer.on('close',function(){
            newBroswer = null;
        })
    }
}

最后将render.js渲染进程的脚本引入index.html(主进程的页面),就可以触发,效果如下:
electron入门(16.0版本亲测可用)

主进程与渲染进程的通信

其实和vue/react的send,on很相似,进程也是相对应了其中的父子组件。
主进程借助了ipcMain模块;渲染进程借助了ipcRenderer模块,大体语法如下:

发送事件:

ipcMain/ipcRenderer.send(eventName, data)

接受事件:

ipcMain/ipcRenderer.on(eventName, ((event, avg) => {
	console.log(event)		//事件的对象信息
	console.log(avg)		//具体的传递数据
}))

最常用的其实就是按钮点击或者进程加载进行发射和接受,整体代码如下:

main.js

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

app.on('ready',function(){
    const mainWindow = new BrowserWindow({
        height:500,
        width:800,
        webPreferences:{
            // 开启node
            nodeIntegration: true,
            contextIsolation: false,
            // 开启remote
            enableRemoteModule:true,
        }
    });

    require('@electron/remote/main').initialize()
    require('@electron/remote/main').enable(mainWindow.webContents)


    mainWindow.loadFile('index.html');
    mainWindow.webContents.openDevTools();

    //主进程接受事件
    ipcMain.on('childToMain', (event, arg) => {
    	//接受后的回复事件
        event.reply('replyChildToMain', '主进程给你回消息了')
        console.log( arg)
    })
    //主进程发射事件
    setTimeout(() => {
        mainWindow.webContents.send('mainToChild', '主进程给子进程发消息')
    }, 3000)


})
// 当所有窗口被关闭了,退出。
app.on('window-all-closed', function() {
    if (process.platform != 'darwin') {
        app.quit();
    }
});

render.js

const {BrowserWindow} = require('@electron/remote')
const {ipcRenderer} = require('electron')
const open_new = document.querySelector('span');


window.onload = function(){
    //子进程发射事件
    ipcRenderer.send('childToMain', '子进程给父进程发消息')
    //子进程接受事件
    ipcRenderer.on('replyChildToMain', (event, arg) => {
        console.log(arg)
    })
    ipcRenderer.on('mainToChild', (event, arg) => {
        console.log(arg)
    })
    open_new.onclick = ()=>{
        var newBroswer = new BrowserWindow({
            width:400,
            height:400,
            webPreferences:{
                // 开启node
                nodeIntegration: true,
                contextIsolation: false,
            }

        });

        newBroswer.loadFile('render.html')
        newBroswer.webContents.openDevTools();
        newBroswer.on('close',function(){
            newBroswer = null;
        })
    }
}

在渲染进程中点击button触发的发射事件:

render.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>渲染进程</h1>
    <button class = "sendBtn">发送消息给main进程</button>
<script>
    const {ipcRenderer} = require('electron')
    const sendBtn = document.querySelector('.sendBtn')
    sendBtn.onclick = () => {
        console.log(111)
        ipcRenderer.send('childToMain', '子进程通过按钮给父进程发消息')
    }
</script>
</body>
</html>

自定义Menu菜单

通过引入electron中Menu函数解析模板可以自定义导航栏部分

const  { Menu } = require('electron');
const Menus = [
    {
        label:'Files',
        submenu:[
            {
                label: '网页版',
                role: 'help',
                submenu: [{
                    label: '网页版',
                    click: function () {
                        electron.shell.openExternal('https://www.jianshu.com/u/1699a0673cfe')
                    }
                }]
            },
            {
                label: '帮助',
                role: 'help',
                submenu: [{
                    label: '帮助文档',
                    click: function () {
                        electron.shell.openExternal('https://www.jianshu.com/u/1699a0673cfe')
                    }
                }]
            }
        ]
    }
];
//编译Menu
const mainMenu = Menu.buildFromTemplate(Menus);
Menu.setApplicationMenu(mainMenu);

当然,也可以通过进程中的frame: false,隐藏窗体的导航栏,通过html自己写点击事件和导航栏模板。
在css中加入-webkit-app-region: drag;可以实现拖拽。

打开文件列表/消息弹窗

打开文件列表使用到了electron中Dialog函数,可以通过Dialog打开文件列表以及消息弹窗等等,与Antd/ElementUi的Dialog弹窗组件类似。

		dialog.showOpenDialog({
            //openFile 允许选择文件
            //openDirectory 允许选择文件夹
            //multiSelections 允许多选
            //showHiddenFiles  显示隐藏文件
            //createDirectory  允许创建文件夹
            properties: ["openFile", "multiSelections", "openDirectory", "showHiddenFiles", "createDirectory"]
        }).then(res => {
            console.log(res)
        })```




	

打开消息弹窗通常在关闭APP时会弹出一个二次确认的弹窗,可以在主进程的关闭事件中写入

mainWindow.on('close', () =>{
        dialog.showMessageBox({
            title: '关闭',
            message: '是否要关闭?',
            type: 'warning',
            buttons: ["关闭", "取消"]
        }).then(res => {
            if(res.response === 1) {
                app.exit()
            }
        })
    })

由于electron迭代更新比较快,网上的很多博客方法都已淘汰(集中于remote模块的使用和配置),因此在不适用旧版本的情况下以上是博主所总结出来的一份,感谢关注。


程序员灯塔
转载请注明原文链接:electron入门(16.0版本亲测可用)
喜欢 (0)