Electron+React 快速搭建一个桌面应用

一、项目技术栈:Electron+react+react-router+antd

1、Electron:electron是一个使用js,html和css等的web技术创建原生桌面应用的框架,他基于chromium和node.js,构建的应用可以在Mac,windows和Linux三个平台上运行。
2、React和react-router在该项目中负责构建单页面应用和路由跳转的实现。
3、Antd作为UI框架。

二、项目搭建

1、创建一个react项目

我们使用目前已经比较成熟的create-react-app脚手架来创建一个react项目,关于这个脚手架的更多资料可以查看:https://facebook.github.io/create-react-app/docs/getting-started。

这里我们使用如下的命令:

npx create-react-app my-app 
cd my-app 
npm start

如果成功,此时可以打开浏览在http://localhost:3000/上会运行着我们新建的项目。
可以通过npm run eject 弹出内建,方便看出有哪些安装的依赖。

2、引入electron

npm i electron --save-dev

安装成功后还不能直接运行一些命令,需要先进行一些配置,至少要有个electron需要用到的main.js入口文件(根目录下)。

3、配置

①在package.json中配置入口文件,具体如下:

image.png

修改启动命令:


image.png

这里的dev想要同时执行两个命令,使用了|将两个命令分开。
其中electron . --debug ,是调试命令需要运行项目同时开启开发者工具,入口文件中会对这个命令进行判断,并开启指定工具。

②main.js文件的编写

(复制github上electron的demo项目中的main.js做一些修改)
如下是当前全部的main.js内容

const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow = null;
//判断命令行脚本的第二参数是否含--debug
const debug = /--debug/.test(process.argv[2]);
function makeSingleInstance () {
    if (process.mas) return;
    app.requestSingleInstanceLock();
    app.on('second-instance', () => {
        if (mainWindow) {
            if (mainWindow.isMinimized()) mainWindow.restore()
            mainWindow.focus()
        }
    })
}
function createWindow () {
    const windowOptions = {
        width: 400,
        height: 300,
        frame:false,
    };
    mainWindow = new BrowserWindow(windowOptions);
    mainWindow.loadURL("http://localhost:3000/");
    // mainWindow.loadURL(path.join('file://', __dirname, '/build/index.html'));
    //接收渲染进程的信息
    const ipc = require('electron').ipcMain;
    ipc.on('min', function () {
        mainWindow.minimize();
    });
    ipc.on('max', function () {
        mainWindow.maximize();
    });
    ipc.on("login",function () {
        mainWindow.maximize();
    });
    //如果是--debug 打开开发者工具,窗口最大化,
    if (debug) {
        mainWindow.webContents.openDevTools();
        require('devtron').install();
    }

    mainWindow.on('closed', () => {
        mainWindow = null
    })
}
makeSingleInstance();
//app主进程的事件和方法
app.on('ready', () => {
    createWindow();
});
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit()
    }
});
app.on('activate', () => {
    if (mainWindow === null) {
        createWindow();
    }
});
module.exports = mainWindow;

如上,注意将主进程的loadUrl设置为localhost:3000,这样可以展示运行在这个地址下的页面。

③安装配置devtron插件

使用如下命令安装:

npm i devtron --save-dev

安装好后:在main.js中进行配置,参考上面main.js文件中的注释。

四、进程通信

项目构建完成后,这里开始讲解一下,react的项目和electron结合使用中的一个应用问题。先把需求提出来,如下图,我们需要在页面中点击右上角最小化时将页面窗口最小化(点击×时的功能以此类推),当点击登录时修改窗口大小,并展示直播页面。


直播器2.gif

要完成这个功能,要使用到Electron的API,这就要先从electron应用结构来说起,electron结构中分为主进程和渲染器进程,如下是electron官网的一段话。

image.png

意思就是说,main.js就是主进程,在主进程中打开的一个web页面就是一个渲染进程,这个web页面也就是该项目中的这个index.html,并且可以直接web页面上通过nodejs的api进行系统级的交互。
如果我们没有使用react,那么没有什么问题,但是在react引入electron就会报错了。所以,要在react中使用,就需要提前将electron赋值给window.electron 以方便使用。在index.html的head中增加了一句js,如下图:

<script>global.electron = require('electron')</script>

此时,回想一下需求,点击“—”时最小化,我们发现触发事件的ui在web页面(react组件)中,而想要操作的mainWindow对象(主进程中打开的那个页面)却在主进程中。所以,尝试一个解决方案,让web页面(react组件)和主进程进行通信。
实现进程通信使用到的api有ipcRenderer和ipcMain.

具体运用如下:

import React from 'react';
import { Layout,Icon } from 'antd';
import "./UserLayout.scss";
import UserRouter from "../../router/userRouter";
const {ipcRenderer} = window.electron;
class UserLayout extends React.Component{
    closeWindow=()=>{
        window.close();
    };
    minWindow=()=>{
        ipcRenderer.send("min");
    };
    render(){
        return(
            <div className="login">
                <div className="top">
                    <div className="top-right">
                        <Icon type="minus" style={{margin:"0 8px"}} onClick={this.minWindow}/>
                        <Icon type="close" onClick={this.closeWindow}/>
                    </div>
                    <div className="top-center">
                        云直播
                    </div>
                </div>
                <div className="main">
                    <div className="main-content">
                        {UserRouter()}
                    </div>
                </div>
            </div>
        )
    }
}

export default UserLayout;

如上点击时执行minWindow,引入ipcRender发送一个消息”min”,main.js中有对应的ipcMain进行监听,请看如下:

//接收渲染进程的信息
    const ipc = require('electron').ipcMain;
    ipc.on('min', function () {
        mainWindow.minimize();
    });

因此,主进程收到消息后,即可对窗口进行处理为最小化,而登录功能与此类似,传递消息到主进程同时跳转页面,主进程收到消息后执行窗口最大化,因此就实现了最初的需求。
同理,当组件有其他操作需要主进程作出反馈时,也可以使用此方案。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容