Electron - 用前端的技术开发桌面应用(二)

678 阅读6分钟

之前已经出了Electron系列第一篇,实现了简单的Hello World,感兴趣的小伙伴可以去翻看:juejin.cn/post/698026…
今天带来第二篇,继续讲讲Electron里面的其他功能用法。

Electron 的运行流程

先来看一个简单的流程

graph LR
Package.json --> 主进程文件 -->读取页面布局和演示 -->IPC执行任务和获取信息

Electron 的主进程和渲染进程

主进程

  • package.json 中的入口文件即main 脚本的进程是主进程
  • 一个Electron应用有且只有一个主进程
  • 主进程可以进行 GUI 相关的原生 API 操作

渲染进程

  • main.js主进程中创建渲染进程
  • 使用BrowserWindow模块,创建和管理应用窗口。当一个BrowserWindow实例被销毁后,相应的渲染进程也被终止
  • Electron使用了Chromium来展示web页面,所以Chromium的多进程架构也被使用到,每个 Electron 中的 web 页面运行在它自己的渲染进程中
  • 主进程控制渲染进程,一个主进程可以控制多个渲染进程

了解了以上内容后,让我们来做一个简单的案例

简单示例

我们来做一个选择餐单的案例。在根目录下建立一个menu.txt的文件,然后写入对应的餐单名。
代码如下: 1.鱼香肉丝 2.小炒肉 3.回锅肉
有了这个文件,我们修改一下 main.js 文件,因为我们要使用 node 里的 fs 模块,所以在设置窗口时,增加全量使用 node.js.

var electron = require('electron') 

var app = electron.app   

var BrowserWindow = electron.BrowserWindow;

var mainWindow = null ;
app.on('ready',()=>{
    mainWindow = new BrowserWindow({
        width:500,
        height:500,
        webPreferences:{ nodeIntegration:true}
    })

    mainWindow.loadFile('index.html')

    mainWindow.on('closed',()=>{
        mainWindow = null
    })

})

然后我们到 index.html 里写一个按钮,然后在按钮下方加一个div标签, 这个 DIV 用来作读取过来内容的容器.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, idivnitial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <Button id="btn">餐单目录</Button><br/>
    <div  id="menu"></div>


</body>
</html>

然后我们可以单独新建一个 renderer 文件夹,名字意思是渲染进程中的操作. 文件夹建立完成后,在文件里新建 index.js 文件,然后再 index.html 页面里先进行引入.正常的js引入形式。最后展示完整的代码:


var fs = require('fs'); 
window.onload = function(){
    var btn = this.document.querySelector('#btn')
    var mybaby = this.document.querySelector('#menu')
    btn.onclick = function(){
        fs.readFile('xiaojiejie.txt',(err,data)=>{
            mybaby.innerHTML = data
        })
    }
} 

最后,执行electron .吗,命令,就可以跳出界面,看到目录了。

Electron Remote 模块

Electron 有主进程和渲染进程, Electron 的 API 方法和模块也是分别可以在主进程和渲染进程中使用。接下来我们就可以使用 Electron Remote 解决在渲染和主进程间的通讯。
在项目根目录下,新建一个 windowDemo.html 文件,然后快速生成 html 的基本结构,编写一个按钮,引入渲染的 js 页面。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
   <Button id="btn">打开新的窗口</Button><br/>
   <script src="renderer/windowDemo.js"></script>
</body>
</html>

在 render 文件夹下,新建一个 windowDemo.js 文件,然后编写如下代码:

 const btn = this.document.querySelector('#btn')
 const BrowserWindow =require('electron').remote.BrowserWindow

window.onload = function(){
    btn.onclick = ()=>{

         newWin = new BrowserWindow({
             width:500,
             height:500,
         })
         newWin.loadFile('menuList.html')
         newWin.on('close',()=>{win=null})

     }
}

顺便新建menuLIst.html页面:



 const btn = this.document.querySelector('#btn')
 const BrowserWindow =require('electron').remote.BrowserWindow

window.onload = function(){
    btn.onclick = ()=>{

         newWin = new BrowserWindow({
             width:500,
             height:500,
         })
         newWin.loadFile('menuLIst.html')
         newWin.on('close',()=>{win=null})

     }
}

然后我们在终端中运行 electron ., 如果一切正常,就可以顺利打开一个新的窗口,这个窗口可以顺利打开主要的功劳就是 electron remote。它让我们有了很多 pc 端的原生能力,这就是简单的electron remote实现后续更为复杂的功能请大家自行研究了。

Electron 创建菜单

之前也创建了好几个菜品,不过那只是展示,这次我们来实现Electron 中使用 Menu 来完成菜单的创建

  • 编写菜单模板 新建一个menuList.js文件:
const { Menu } = require('electron')

var template = [
    {
        label:'江南之乡',
        submenu:[
            {label:'西湖醋鱼'},
            {label:'龙井虾仁'}
        ]

    },
    {
        label:'川菜馆',
        submenu:[
            {label:'小炒肉'},
            {label:'回锅肉'}
        ]
    }
]

var m = Menu.buildFromTemplate(template)

Menu.setApplicationMenu(m)

然后再打开主进程 main.js 文件,在 ready 生命周期中,直接加入下面的代码,就可以实现自定义菜单了

 require('./main/menuList.js')
  • 使用菜单打开新窗口 在菜单中加入 click 事件,代码如下:
const { Menu ,BrowserWindow} = require('electron')


var template = [
    {
        label:'江南之乡',
        submenu:[
            {
                label:'西湖醋鱼',
                //主要代码--------------start
                click:()=>{
                    win = new BrowserWindow({
                        width:500,
                        height:500,
                        webPreferences:{ nodeIntegration:true}
                    })
                    win.loadFile('menuList.html')
                    win.on('closed',()=>{
                        win = null
                    })

                }
                //主要代码----------------end
            },
            {label:'龙井虾仁'}
        ]

    },
    {
        label:'川菜馆',
        submenu:[
            {label:'小炒肉'},
            {label:'回锅肉'}
        ]
    }
]

var m = Menu.buildFromTemplate(template)

Menu.setApplicationMenu(m)

最后打开终端输入 electron . 之后,就可以看到效果了

Electron 制作右键菜单

上面学习了如何设置顶部菜单,我们也作了一个菜单的小案例,这次我们继续学习如何实现右键功能。

  • 菜单快捷键绑定 绑定快捷键的属性是 accelerator 属性,比如我们新打开一个窗口。
accelerator:`ctrl+n`

全部代码还是上面的代码,就不粘贴了。写完代码后,在终端中输入 electron . 运行程序,再用快捷键 ctrl+n 就可以新建一个页面了。这就实现了新建页面的方法。

  • 创建右键菜单 右键菜单的响应事件是写在渲染进程中的,也就是写在 index.html 中的,所以要是使用,就用到到 remote 模块进行操作了。

先来看看右键的相应事件,我们打开 render 文件夹,然后打开 windowDemo.js 文件,编写一个右键菜单的监听事件,代码如下:

window.addEventListener('contextmenu',function(){
    alert(123);
})

使用remote


const { remote} = require('electron')

var rigthTemplate = [
    {label:'粘贴'},
    {label:'复制'}
]

var m = remote.Menu.buildFromTemplate(rigthTemplate)



window.addEventListener('contextmenu',function(e){

    //阻止当前窗口默认事件
    e.preventDefault();
    //把菜单模板添加到右键菜单
    m.popup({window:remote.getCurrentWindow()})

})

最后我们可以在终端中输入 electron . 打开程序进行测试右键菜单功能。

  • 程序打开调试模式 我们可以继续添加一个调试模式的菜单:
mainWindow.webContents.openDevTools()

全部代码如下:

var electron = require('electron') 

var app = electron.app   

var BrowserWindow = electron.BrowserWindow;

var mainWindow = null ;
app.on('ready',()=>{
    mainWindow = new BrowserWindow({
        width:500,
        height:500,
        webPreferences:{ nodeIntegration:true}
    })
    mainWindow.webContents.openDevTools()

    require('./main/menuList.js')

    mainWindow.loadFile('windowDemo.html')

    mainWindow.on('closed',()=>{
        mainWindow = null
    })

})

这样就实现了打开窗口,直接进入调试模式,极大的提高了调试效率.

Electron 中通过链接打开浏览器

我们知道在渲染进程中默认加入一个 <a> 标签,进行跳转默认是直接在窗口中打开,而不是在浏览器中打开的,如果我们想在默认浏览器中打开,需要怎么操作?那就是electron shell

  • 默认打开示例 我们先来看一下,在 electron 中默认打开一个链接是什么样的,在项目根目录,新建一个 demo.html 文件,编写一个 <a> 标签,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>
        <a href="https://www.baidu.com"></a>
    </h1>
</body>
</html>
  • 使用Shell在浏览器中打开 在 <a> 标签中加入 id
<a id="hrefs" href="https://www.baidu.com"></a>

在 render 文件夹下,新建一个 demo1.js 文件,先在文件首页中引入 shell, 然后编写响应事件 click

var { shell } = require('electron')

var hrefs = document.querySelector('#hrefs') 

aHref.onclick = function(e){
    e.preventDefault()
    var href = this.getAttribute('href')
    shell.openExternal(href)
}

html 中引入 demo1.js 文件

<script src="./renderer/demo1.js"></script>

这样就实现了在浏览器中打开链接的操作了。

结语:本文是Electron系列第二篇,由于事情比较多,没有按时的学习并输送文章,不过只要有时间,还是会慢慢学习总结的。我们的学习之路还没有结束,Electron里面的对话框操作、断网提醒、消息通知、剪切板等,都会在后期文章中陆续出现。