electron的第一次亲密接触——初次制作的方案与踩坑(三)

这一篇就主要讲一讲第一次制作electron桌面应用的具体过程以及踩坑。

初次制作主要用的是electron+react的路线,react负责渲染,如果使用vue的话思路大同小异,毕竟框架仅负责渲染进程。

首先我用一个已经完成的react项目进行测试,在react项目的package.json中添加“homepage”:“/.”,然后进行build,之后在build文件夹中,安装electron,打包构建应用,启动桌面应用,react项目正常显示。这只是个小测试,实际用途不大。第一点是,在package.json中添加“homepage”:“/.”之后,build中的index.html可以直接访问并显示项目,引入electron仅仅只是给他套了一个桌面应用的壳;第二点是,构建的应用的所有功能实际上是使用react在前端进行实现的,它与本地资源、环境没有任何关联与操作,所以只能算作一次类似helloworld的操作。

我的第一个electron应用是个数据提取工具,我做了如下的规划:

1、主进程,使用node语言,负责本地资源的调用以及后端逻辑的处理;

2、渲染进程,使用react框架,仅负责前端的渲染;

3、数据资源使用sqlite,本地调用快捷方便,同时保证数据安全。

第一步首先用creat-react-app构建react项目,然后在react项目中加入electron的主文件main.js。

构建窗口,在这里,我就不展示main.js的构建窗口的代码了,官方文档写的很清楚,网上也可以查询到。不过在这里说一下第一个小坑,在构建mainWindows的时候,webPreferences中的配置参数,nodeIntegration与 preload两个参数实际上是冲突的,一旦你配置了预加载preload.js文件之后,nodeIntegration:true的配置就会失效。如果你只是简单的使用html页面来负责渲染,可以开启nodeIntegration,会比较方便,如果使用react或者Vue框架的话,建议使用preload配置。此外,还有一个建议,将electron 的main.js文件以及预加载preload.js文件都放在react项目的public文件夹中,这样在构建 react项目时,两个文件就会被直接引入到build文件中,package.json 中添加"main": "public/main.js",便于开发过程中的测试。

//关于node模式和预加载文件的设置
const mainWindow = new BrowserWindow({
    width: 800,
    height: 1000,
    webPreferences: {
      nodeIntegration: true,          
      preload: path.join(__dirname, 'preload.js')
    }
  })

 接下来,就是本次制作最大的难点,主线程与渲染线程之间的沟通。

根据官方文档的说明,主线程与渲染线程的沟通主要是通过ipcMain与ipcRenderer进行信息传递的:

//以下代码是写在main.js中
const { BrowserWindow,ipcMain } = require('electron')
function createWindow(
    const mainWindow = new BrowserWindow()
    //主进程发送信号“message”,传递参数a,a可以是string,array,object,下同
    mainWindow.webContents.send('message',a)
//主进程监听到信号“message”,终端打印传递来的参数arg
    ipcMain.on('message', (event, arg) => {       
         console.log(arg)})

)
//以下代码是在渲染部分
//渲染进程发送信号“message”,传递参数a
ipcRenderer.send('message',a);
//渲染进程监听到信号“message”,终端打印传递来的参数arg
ipcRenderer.on('message',(event,arg)=>{
          console.log(arg)})
});

以上就在主进程与渲染进程形成闭环,进行信息的传递以及函数的调用。主进程的监听与发送相对简单,按照官方文档写在main.js中即可,但是想在react中调用ipcRenderer,实现的过程颇为复杂。

我首先在react中尝试使用

const {ipcRenderer } = require('electron');

react报错。

然后尝试改为import的方式:

import {ipcRenderer }  from 'electron'

依旧react报错。

只能继续寻找解决方案。我在网上搜索到了一个方法,然后进行尝试。

const electron = window.require('electron');
const {ipcRenderer} = electron;

依旧报错。但是这个方法给了我灵感,调用window,或许有想不到的收获。

查找官方文档,然后研究了github中electron-react-boilerplate模板,在官网上有这么一段代码引起了我的注意(如下所示,在electron-react-boilerplate上也有类似的代码),我就在preload.js加入了该段代码进行测试,而后在react中加入console.log(window)的语句。

preload.js

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electron', {
    setTitle: (title) => ipcRenderer.send('set-title', title)
})

npm start启动react,但结果依然不尽如人意,并没有什么特别的发现。就在这时,我突然意识到一个问题,单单调用react,electron实际并未介入其中。只能将react打包,然后在build文件中测试electron,查看后台,我在输出window中看到了electron和下一层的setTitle,豁然开朗。然后我就在react的代码中加入了如下代码,再次打包,测试electron,在主进程可以监听“set-title”可以获取到a参数,至此,主进程与react负责的渲染进程的通信打通了。

window.electron.setTitle(a)// a为传递的参数

而后又遇到一个问题,就是在开发的时候打包进行测试,有点麻烦了。于是我参考了网上的一个方法,将主进程中的mainWindow.loadFile("index.html") 改为

  mainWindow.loadURL("127.0.0.1:3000") //127.0.0.1:3000 react的测试地址

然后先用npm start启动react ,注意,由于react框架中引入了electron模块的内容,所以在单独启用react项目时,是不会显示任何东西的,会报错“ Cannot read properties of undefined (reading '函数名')”,在preload中定义的函数由于没有启动electron,会显示未定义。然后在用electron . 启动electron的测试,在应用中页面呈现,功能加载,并且修改代码之后保存,页面也会重新加载,便于开发维护。

初次开发的整体思路大致如此,最后,再写一个小坑,解决了之后可以让代码更方便简洁。关于ipcRenderer函数的写法,如ipcRenderer.send()函数有两个参数,第一个是信号的名称,第二个是传递的参数,preload.js作如下修改:

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electron', {
    setTitle: (message,obj) => ipcRenderer.send(message, obj)
    recieveTitle:(message,obj) => ipcRenderer.on(message, obj)
})


这样在react中使用ipcRenderer的时候,只需要调用setTitle()和recieveTitle()两个参数就可以了,通过不同的信号message实现不同的传参调用。

软件制作的难点就是以上这些了,解决了这些问题,其他的就是常规的前后端开发。最后再上一次软件截图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQwNTQxOTQ1,size_20,color_FFFFFF,t_70,g_se,x_16

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值