Electron

如果你可以建一个网站,你就可以建一个桌面应用程序。 Electron 是一个使用 JavaScript, HTML 和 CSS 等 Web 技术创建原生程序的框架,它负责比较难搞的部分,你只需把精力放在你的应用的核心上即可。

一、介绍
  1. Web 技术
    Electron 基于 Chromium 和 Node.js, 让你可以使用 HTML, CSS 和 JavaScript 构建应用。
  2. 开源
    Electron 是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目。
  3. 跨平台
    Electron 兼容 Mac, Windows 和 Linux, 它构建的应用可在这三个操作系统上面运行。
二、入门
  1. Electron的API
    Electron API
  2. Electron Fiddle
    Electron Fiddle 最简单的 Electron 入门方式。

    Electron Fiddle 让您可以创建和进行小型 Electron 实验。它会在打开后用一个快速启动模板迎接你 - 更改一些东西,选择你想要用以运行它的 Electron 版本,随意玩耍。然后,将您的 Fiddle 保存为一个 GitHub Gist 或保存到一个本地文件夹。一旦将其推送到 GitHub ,任何人都可以通过仅仅在地址栏中输入它来快速尝试您的 Fiddle 。

  3. Electron Forge
    Electron Forge

    The command line interface for ambitious Electron applications

    	npm install -g electron-forge
    	
    	# create a new project
    	electron-forge init my-new-project
    	cd my-new-project
    	electron-forge start
    
  4. 快速启动
    electron-quick-start
    # 克隆示例项目的仓库
    $ git clone https://github.com/electron/electron-quick-start
    
    # 进入这个仓库
    $ cd electron-quick-start
    
    # 安装依赖并运行
    $ npm install && npm start
    
  5. Electron-vue
    Electron-vue

    该项目的目的,是为了要避免使用 vue 手动建立起 electron 应用程序。electron-vue 充分利用 vue-cli 作为脚手架工具,加上拥有 vue-loader 的 webpack、electron-packager 或是 electron-builder,以及一些最常用的插件,如vue-router、vuex 等等。

三、项目实战
1、electron-quick-start
  1. clone 之后 npm i 或者 yarn
  2. npm start 或者 electron .
  3. 代码
//主进程
const {app, BrowserWindow} = require('electron')	//引入
let mainWindow										//定义窗口的变量名
function createWindow () {							//创建窗口函数
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true	//是否完整的支持 node. 默认值为true. (有坑)
    }
  })
  mainWindow.loadFile('index.html')		//加载页面,可以是本地页面,也可以是网页链接
  //mainWindow.loadURL('https://www.baidu.com');
  mainWindow.on('closed', function () {	//关闭时释放变量
    mainWindow = null
  })
}
app.on('ready', createWindow)			//app ready事件
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
app.on('activate', function () {
  if (mainWindow === null) createWindow()
})
2、electron-vue
  1. vue init simulatedgreg/electron-vue my-project
  2. yarn
  3. yarn run dev
    electron-vue
3、pddcjdz

入口文件 main.js(主进程)

mainWindow = new BrowserWindow({
    width: 1300,
    height: 800,
    webPreferences: {
      //是否完整的支持 node. 默认值为true  嵌入页面的话某些情况 需要关闭nodeIntegeration来兼容web资源的依赖加载。
      nodeIntegration: false,	
      //当设置为 false, 它将禁用同源策略 (通常用来测试网站), 如果此选项不是由开发者设置的
      webSecurity: false,		
      //允许一个 https 页面运行 http url 里的资源,包括 JavaScript, CSS 或 plugins.
      allowRunningInsecureContent: true,	
      //在页面运行其他脚本之前预先加载指定的脚本 无论页面是否集成Node, 此脚本都可以访问所有Node API 脚本路径为文件的绝对路径。
      preload: path.resolve(path.join(__dirname, './src/preload.js'))
    }
  })

入口中引入的脚本文件 preload.js

const electron = require('electron')		//引入electron
const request = require('superagent');		//引入superagent
// DOM变异事件 https://developer.mozilla.org/zh-CN/docs/Web/Events#DOM%E5%8F%98%E5%BC%82%E4%BA%8B%E4%BB%B6
document.addEventListener('DOMNodeInserted', (event) => {	
    window.cjdz = {
        request,	//把 爬虫 request 和 electron暴露出去。
        electron,
        version: 1.0
    }
});
//如果 nodeIntegration 值为true的话,是可以不用把electron暴露出去的,后面在页面中可以直接 使用 require('electron')来获取electron,但是为true的话代表使用electron集成的node,会和其他的一些地方有冲突; 如果为false的话,就需要把electron暴露出去,通过 window.把它找出来。
4、开发

一个electron项目只要一个主进程(main.js)
可以有多个渲染进程
electron使用Chromium来展示web页面,每个页面运行在自己的渲染进程中。
正常项目开发即可。

四、打包

1、electron-packager
electron-packager
2、electron-builder

A complete solution to package and build a ready for distribution Electron, Proton Native or Muon app for macOS, Windows and Linux with “auto update” support out of the box.
一个完整的解决方案,可以为macOS,Windows和Linux打包并构建一个可供分发的 Electron,Proton Native 或Muon应用程序,并提供开箱即用的“自动更新”支持。

electron-builder比electron-packager有更丰富的的功能,支持更多的平台,同时也支持了自动更新。除了这几点之外,由electron-builder打出的包更为轻量,并且可以打包出不暴露源码的setup安装程序。

electron-builder
electron-builder(中文)
打包一般 是:–mac(Mac)、–x64(window64)、–ia32(window32),Linux一般比较少:–linux;

"build": {
  "productName": "my-project",	//打包名
  "appId": "org.simulatedgreg.electron-vue",	//appID
  "directories": {
    "output": "build"			//输出目录
  },
  "files": [					//打包文件目录
    "dist/electron*"
  ],
  "dmg": {						//Mac配置  macOS DMG选项
    "contents": [
      {
        "x": 410,
        "y": 150,
        "type": "link",
        "path": "/Applications"
      },
      {
        "x": 130,
        "y": 150,
        "type": "file"
      }
    ]
  },
  "mac": {		//与构建macOS目标的方式相关的选项。
    "icon": "build/icons/icon.icns"		//Mac图标
  },
  "win": {		//与构建Windows目标的方式相关的选项。
    "icon": "build/icons/icon.ico"		//windows图标
  },
  "linux": {	//与构建linux目标的方式相关的选项。
    "icon": "build/icons"				//Linux图标
  }
}

打包scripts

"scripts": {
  "start": "electron .",
  "pack": "electron-builder --dir",
  "mac": "electron-builder --mac",
  "win64": "electron-builder --win --x64",
  "win32": "electron-builder --win --ia32"
},

yarn / npm run mac //会生成.dmg文件
yarn / npm run win64 //生成.exe文件
yarn / npm run win32 //生成.exe文件
注意:
win64和win32 生成.exe文件是同一个文件源,所以要打包之后标注一下然后在打包另一个系统。

electron-builder的使用
electron-builder的用法
Building(构建参数):
Command Line Interface (CLI)

参数 平台 类型/参考
–mac, -m, -o, --macos Build for macOS array
–linux, -l Build for Linux array
–win, -w, --windows Build for Windows array
–x64 Build for x64 (64位安装包) boolean
–ia32 Build for ia32(32位安装包) boolean
–armv7l Build for armv7l boolean
–arm64 Build for arm64 boolean
–dir Build unpacked dir. Useful to test boolean
–prepackaged, --pd 预打包应用程序的路径 以可分发的格式打包
–projectDir, --project 项目目录的路径 默认为当前工作目录
–config, -c 配置文件路径 默认为electron-builder.yml

发布配置
Publish

图标生成
window和Mac图标生成

其他需求
1、点击关闭弹框确认

在主进程中对 mainWindow 进行 close事件监听,不是closed。
引用electron的 dialog

const {dialog} = require('electron');
mainWindow.on('close', (e) => {
  e.preventDefault(); //阻止事件默认行为
  let message = '退出后,如需使用需重新登录,请确认是否退出?';
  //let message = copyTaskFlag ? '退出后,正在抓取的商品将无法继续抓取,请确认是否最小化?' : '退出后,如需使用需重新登录,请确认是否退出?'
  dialog.showMessageBox({	//引用dialog
    type: 'info',
    title: '退出拼多多超级店长',
    defaultId: 0,
    message: message,
    buttons: ['最小化','直接退出']	
  },(index)=>{
    if(index===0){		//对应 buttons 数组的下标
      e.preventDefault();
      mainWindow.minimize();	//最小化
    } else {
      mainWindow = null;
      app.exit();				//退出应用 立即退出程序
      //app.quit();				//退出应用 尝试关闭所有窗口 
    }
  })
});

两种退出:exit()和quit()

  1. exit:
    直接退出整个应用
  2. quit:
    不会直接退出应用,是关掉客户端会留在任务栏里面。
    在mianWindow的close事件用这个的话,会弹出两次弹框。如果需要这种退出的话需要单独写 flag 处理一下。
2、主进程与渲染进程通信

ipcMain
ipcRenderer
ipcMain:在主进程中使用时,它处理从渲染器进程(网页)发送出来的异步和同步信息。 从渲染器进程发送的消息将被发送到该模块。
ipcRenderer:可以使用它提供的一些方法从渲染进程 (web 页面) 发送同步或异步的消息到主进程。 也可以接收主进程回复的消息。
简单实例:
Q:点击关闭按钮的时候,在渲染进程中有正在复制的时候点击关闭按钮展示一段话,没有正在复制的时候展示另一段话。
主进程:

const {ipcMain} = require('electron');
let copyTaskFlag = false;		//定义一个变量 flag	
ipcMain.on('copyTask-message', (event, arg) => {	//监听渲染进程事件 on 监听的 事件名要和 渲染进程的事件名一致。
  copyTaskFlag = arg;			//arg 为渲染进程事件传过来的值
});

渲染进程:

const { ipcRenderer } = require('electron')		//渲染进程中引入
ipcRenderer.send('copyTask-message', options);	//send
3、客户端右键

一个新的客户端右键是没有任何东西的,需要自定义的。

//右键菜单:1 调用 electron的 menu 中的配置 https://electronjs.org/docs/api/menu-item
	let electron = require('electron');
    const remote = require('electron').remote;
    const Menu = remote.Menu;
    const MenuItem = remote.MenuItem;
    var menu = new Menu();
    menu.append(new MenuItem({ label: '复制', selector: "copy:" ,role: "copy:" }));
    menu.append(new MenuItem({ type: 'separator' }));
    menu.append(new MenuItem({ label: '剪切', selector: "cut:", role: "cut:"}));
    menu.append(new MenuItem({ type: 'separator' }));
    menu.append(new MenuItem({ label: '粘贴', selector: "paste:", role: "paste:"}));
    window.addEventListener('contextmenu', function (e) {
      e.preventDefault();
      menu.popup(remote.getCurrentWindow());
    }, false);
//右键菜单:2 使用document的方法。
    let electron = require('electron');
    const remote = electron.remote;
    const Menu = remote.Menu;
    const MenuItem = remote.MenuItem;
    let menu = new Menu();
    menu.append(new MenuItem({ label: '复制', click: function() {
        document.execCommand("copy", "false", null);
    }}));
    menu.append(new MenuItem({ type: 'separator' }));
    menu.append(new MenuItem({ label: '黏贴', click: function() {
        document.execCommand("paste", "false", null);
    }}));
    menu.append(new MenuItem({ type: 'separator' }));
    menu.append(new MenuItem({ label: '刷新', click: function() {
        location.reload();
    }}));
    window.addEventListener('contextmenu', function (e) {
      e.preventDefault();
      menu.popup(remote.getCurrentWindow());
    }, false);
4、remote 模块

remote 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通讯(IPC)的简便途径。
在Electron中, GUI 相关的模块 (如 dialog、menu 等) 仅在主进程中可用, 在渲染进程中不可用。 为了在渲染进程中使用它们, ipc 模块是向主进程发送进程间消息所必需的。 使用 remote 模块, 你可以调用 main 进程对象的方法。

在渲染进程中:
1、使用dialog

const electron = require('electron').remote;
const dialog = electron.dialog;

2、BrowserWindow

const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://blog.csdn.net/guoqiankunmiss')

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐