写的跟憨逼一样的文档是阻碍恐怖直立猿在开发中不可逾越的障碍
配置环境
网不好安装electron很难,用cnpm也可以,但是cnpm安装的包在打包的时候会很慢
第一次知道原来命令行默认是不走玄学的,这个1080,是玄学上网的端口
yarn config set proxy http://127.0.0.1:1080
// 记得删除
yarn config delete proxy
如果不行的话,cnpm硬怼吧
准备工作
公司的技术栈是react,如果是vue的话,会简单很多,建议各位了解下vue-electron,这个react好像没有,多说无益,vue牛逼,另外github的star早已反超react,没错我很喜欢vue
入口文件
electron启动是根据package.json
中的main
字段来决定的,也是electron中的主线程
比如
// package.json
{
"main": "electron/main.js",
"scripts": {
"start:elec": "electron electron/main.js"
}
}
另外给一份main.js配置,记得安装包,主要参考electron-quick-start
// electron.app管理整个应用程序生命周期,比如启动销毁等
// electron.BrowserWindow负责创建窗口
const { app, BrowserWindow } = require('electron')
const isDev = require('electron-is-dev');
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
mainWindow.loadFile('index.html')
isDev && mainWindow.webContents.openDevTools()
}
function createDevTools() {
//BrowserWindow.addDevToolsExtension(path.join(__dirname, 'chrome-extensions', 'react-dev-tools'));
}
// 等待electron初始化完成,有两种方法,
// 适合主流
app.on('ready', function () {
createWindow()
isDev && createDevTools()
})
// whenReady应该是新方法,但可能会有问题, 等过个一年半载可以用这个,返回一个Promise
// [参考](https://github.com/electron/fiddle/pull/362)
// app.whenReady().then(() => {
// createWindow()
// app.on('activate', function () {
// if (BrowserWindow.getAllWindows().length === 0) createWindow()
// })
// })
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
react-app-rewired
使用create-react-app
创建工程如果水平高的话,可以自己手动改webpack,或者用react-app-rewired
,配置起来会简单很多,scripts
中的字段改成react-app-rewired
开头,具体可以查查
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
}
// 根目录config-verrides.js
module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
};
electron-is-dev
区分开发环境还是生产环境,开发和生成用的配置肯定会有点区别,用法很简答
const isDev = require('electron-is-dev');
// 返回的是一个布尔值,开发环境true,可以在控制台打印输出下
concurrently,wait-on,cross-env
打开多个命令行的,electron结合react的思路相当于是一个命令行运行react,另一个命令行运行electron,加载win.loadURL('http://localhost:3000'),concurrently可以用一个命令启动两个命令行
wait-on就是等待http://localhost:3000启动成功后再运行
使用cross-env
,在调试electron的时候其实不需要启动浏览器,所以"start:elec": "cross-env BROWSER=none xxxx
// 不要照抄,根据自己实际情况来
"scripts": {
"start": "react-app-rewired start",
"start:elec": "concurrently \"npm run start:react\" \"npm run start:electron\"",
"start:react": "cross-env BROWSER=none react-app-rewired start",
"start:electron": "wait-on http://localhost:3000 && electron app"
},
Electron 使用whenReady会有很多问题,慎用,目前版本建议用on('ready')
如何和react相结合
React和electron相结合会报些奇怪的错误,毕竟是两种不同的框架,electron也不是专门给react做的,常见的错误
fs.existsSync is not a function
简单的说,用create-react-app创建项目添加electron时,默认webpack输出的是web环境,react和vue开发的时候就是这个,但是在解析electron行不通,导致模块报错,可以看这里,target有electron-main
的选项
在这里先列出一种方法
把electron挂在到electron的window
主线程的引入方式不变
const { app, BrowserWindow } = require("electron");
渲染线程
// test.js
import React from "react";
const remote = window.require("electron").remote
const BrowserWindow = remote.BrowserWindow;
export const Index = () => {
const btn = () => {
const newWin = new BrowserWindow({
width: 500,
height: 500,
webPreferences: {
nodeIntegration: true,
},
});
newWin.loadURL("https://www.baidu.com/");
};
return (
<div>
<button onClick={btn}>弹窗测试</button>
</div>
);
};
当然,最好修改webpack的target方式,但在某些场景可能会有问题,灵活选择
electron在react中打开子窗口该怎么办
electron打开窗口有两种方式
- win.loadURL()
- win.loadFile()
loadFile一般是打开静态页面的时候,比如react打包好生成静态文件后用loadFile加载,但是,有点问题,首页可以,子窗口呢?我想把子窗口用react组件的方式编写,但是electron不认js文件,也不可能专门给子页面打包成一个静态的,那这样也low的可以, 唯一的选择就是用loadURL的方式,那具体怎么做,简单,用路由
- 注册路由,只注册就行,什么
<Link to="/test/">跳转</Link>
,这个东西不用管,注册到哪里,看需求了,举个栗子
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Index } from "./components/Index";
import {Camera} from './components/Camera'
function App() {
return (
<div className="App">
<Router>
<Route path="/" exact
component={Index}></Route>
// Camera是我要打开的子弹窗
<Route path="/camera/" component={Camera}></Route>
</Router>
</div>
);
}
export default App;
- 跳转路由
export const Index = () => {
const btn = () => {
const newWin = new BrowserWindow({
width: 500,
height: 500,
webPreferences: {
nodeIntegration: true,
},
});
// 由这里跳转
newWin.loadURL("http://localhost:3000/camera/");
};
return (
<div>
<button onClick={btn}>弹窗测试</button>
</div>
);
};
当然我这种思路也有局限,还是要依赖服务器,服务器挂了,electron就挂了,不是纯静态exe,暂时还没想到怎么脱离web做成纯桌面程序,有思路的老哥麻烦指点下