前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Electron启程

Electron启程

作者头像
码客说
发布2019-10-21 17:17:10
5.6K1
发布2019-10-21 17:17:10
举报
文章被收录于专栏:码客码客

前言

Electron 可以让你使用纯 JavaScript 调用丰富的原生(操作系统) APIs 来创造桌面应用。 你可以把它看作一个 Node. js 的变体,它专注于桌面应用而不是 Web 服务器端。

这不意味着 Electron 是某个图形用户界面(GUI)库的 JavaScript 版本。 相反,Electron 使用 web 页面作为它的 GUI,所以你能把它看作成一个被 JavaScript 控制的,精简版的 Chromium 浏览器。

起步

代码语言:javascript
复制
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start

创建窗口

代码语言:javascript
复制
const { app, BrowserWindow } = require('electron')

// 保持对window对象的全局引用,如果不这么做的话,当JavaScript对象被
// 垃圾回收的时候,window对象将会自动的关闭
let win

function createWindow () {
  // 创建浏览器窗口。
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  // 加载index.html文件
  win.loadFile('index.html')

  // 打开开发者工具
  win.webContents.openDevTools()

  // 当 window 被关闭,这个事件会被触发。
  win.on('closed', () => {
    // 取消引用 window 对象,如果你的应用支持多窗口的话,
    // 通常会把多个 window 对象存放在一个数组里面,
    // 与此同时,你应该删除相应的元素。
    win = null
  })
}

// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow)

// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
  // 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
  // 否则绝大部分应用及其菜单栏会保持激活。
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // 在macOS上,当单击dock图标并且没有其他窗口打开时,
  // 通常在应用程序中重新创建一个窗口。
  if (win === null) {
    createWindow()
  }
})

// 在这个文件中,你可以续写应用剩下主进程代码。
// 也可以拆分成几个文件,然后用 require 导入。

主进程和渲染进程

Electron 运行 package.jsonmain.js 脚本的进程被称为主进程

在主进程中运行的脚本通过创建web页面来展示用户界面。

一个 Electron 应用总是有且只有一个主进程。

每个 Electron 中的 web 页面运行在它自己的渲染进程中。

主进程管理所有的web页面和它们对应的渲染进程。 每个渲染进程都是独立的,它只关心它所运行的 web 页面。

Electron同时在主进程和渲染进程中对Node.js 暴露了所有的接口。

主进程和渲染进程模块

两种进程都可用的模块

  • clipboard 在系统剪贴板上执行复制和粘贴操作。
  • crashReporter 将崩溃日志提交给远程服务器。
  • nativeImage 使用 PNG 或 JPG 文件创建托盘、dock和应用程序图标。
  • shell 使用默认应用程序管理文件和 url。

Main Process 模块

  • app 控制你的应用程序的事件生命周期。
  • autoUpdater 使应用程序能够自动更新
  • BrowserView 创建和控制视图,相当于Android中的Fragment。
  • BrowserWindow 创建和控制浏览器窗口,相当于Android中的Activity。
  • contentTracing 从Chromium的内容模块收集跟踪数据,以查找性能瓶颈和缓慢的操作。
  • dialog 显示用于打开和保存文件、警报等的本机系统对话框。
  • globalShortcut 在应用程序没有键盘焦点时,监听键盘事件。
  • inAppPurchase Mac App Store中的应用内购买。
  • ipcMain 从主进程到渲染进程的异步通信。
  • Menu 创建原生应用菜单和上下文菜单。
  • MenuItem 添加菜单项到应用程序菜单和上下文菜单中。
  • net 使用Chromium的原生网络库发出HTTP / HTTPS请求。
  • netLog 网络请求日志。
  • powerMonitor 监视电源状态的改变。
  • powerSaveBlocker 阻止系统进入低功耗 (休眠) 模式。
  • protocol 注册自定义协议并拦截基于现有协议的请求。
  • screen 检索有关屏幕大小、显示器、光标位置等的信息。
  • session 管理浏览器会话、cookie、缓存、代理设置等。
  • systemPreferences 获取system preferences。
  • 触控板 为原生macOS应用创建TouchBar布局。
  • Tray 添加图标和上下文菜单到系统通知区。
  • webContents 渲染以及控制 web 页面。

Renderer Process 模块

  • desktopCapturer 从桌面上捕获音频和视频的媒体源信息。
  • ipcRenderer 从渲染器进程到主进程的异步通信。
  • remote 在渲染进程中使用主进程模块。
  • webFrame 自定义渲染当前网页。

进程间通讯

渲染进程=>主进程=>渲染进程

1)异步

在主进程中

代码语言:javascript
复制
const { ipcMain } = require('electron')

ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg) // prints "ping"
  event.reply('asynchronous-reply', 'pong')
})

在渲染器进程 (网页) 中

代码语言:javascript
复制
const { ipcRenderer } = require('electron')

ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')

2)同步

在主进程中

代码语言:javascript
复制
const { ipcMain } = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg) // prints "ping"
  event.returnValue = 'pong'
})

在渲染器进程 (网页) 中

代码语言:javascript
复制
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"

主进程=>渲染进程

在主进程中

代码语言:javascript
复制
const { ipcMain } = require('electron')

let rtmpWindow = new BrowserWindow({
    width: 400,
    height: 600,
    frame: false,
    hasShadow: false,
    show: false,
    title: "",
    webPreferences: {
      nodeIntegration: true
    }
  });
rtmpWindow.loadFile("views/rtmp.html");
rtmpWindow.webContents.openDevTools()


rtmpWindow.webContents.on('did-finish-load', () => {
  //下面的这行代码要在上面的BrowserWindow加载完成之后调用
  rtmpWindow.webContents.send('asynchronous-msg',"test");
})

在渲染器进程 (网页) 中

代码语言:javascript
复制
const { ipcRenderer } = require('electron')

ipcRenderer.on('asynchronous-msg', (event, arg) => {
  console.log(arg) // prints "pong"
})

渲染进程=>渲染进程

使用全局共享属性

使用全局共享属性或者用 Storage API( localStoragesessionStorage 或者 IndexedDB)。

但不具备事件机制,没有实质的通信功能。

代码语言:javascript
复制
// 主进程中在global上自定义对象
global.saveDefault= {
  token: 'default value',
  name: 'default value',
  password: 'default value',
}
 
// 在登录页 In page 1
require('electron').remote.getGlobal('saveDefault').token= 'token'
require('electron').remote.getGlobal('saveDefault').name= 'name'
 
 
// 在主页 In page 2 就可以获取到
console.log(require('electron').remote.getGlobal('saveDefault').name)
console.log(require('electron').remote.getGlobal('saveDefault').token)
console.log(require('electron').remote.getGlobal('saveDefault').password)
利用主进程做消息中转
代码语言:javascript
复制
// 渲染进程1
ipcRenderer.send('ping-event', 'ping')

// 在主进程中
ipcMain.on('ping-event', (event, arg) => {
  yourWindow.webContents.send('pong-event', 'something');
}
 
// 渲染进程2
ipcRenderer.on('pong-event', (event, arg) => {
     // do something
  }
)
使用 ipcRenderer.sendTo()
代码语言:javascript
复制
// 渲染进程
ipcRenderer.sendTo(webContentsId, channel, [, arg1][, arg2][, ...])
ipcRenderer.sendTo(winId, 'ping', 'someThing')
利用 remote 接口直接获取渲染进程发送消息
代码语言:javascript
复制
// 渲染进程
// 获取窗口的id
remote.BrowserWindow.fromId(winId).webContents.send('ping', 'someThing');
获取进程id的方法

第一种: 通过 global 设置和获取

代码语言:javascript
复制
// 主进程中在global上自定义对象
global.winIds= {
  win1Id : win1.id,
  win2Id : win2.id
}

// 主进程获取
global.winIds["win1Id"];

// 渲染进程获取
require('electron').remote.getGlobal('winIds').win1Id

第二种是: 主进程创建事件,发送信息(不推荐)

代码语言:javascript
复制
// 主进程中
win1.webContents.send('distributeIds',{
    win2Id : win2.id
});
 
win2.webContents.send('distributeIds',{
    win1Id : win1.id
});

页面数据共享

在两个网页(渲染进程)间共享数据最简单的方法是使用浏览器中已经实现的 HTML5 API。 其中比较好的方案是用 Storage API( localStoragesessionStorage 或者 IndexedDB)。

你还可以用 Electron 内的 IPC 机制实现。将数据存在主进程的某个全局变量中,然后在多个渲染进程中使用 remote 模块来访问它。

在主进程中

代码语言:javascript
复制
global.sharedObject = {
  someProperty: 'default value'
}

在第一个页面中

代码语言:javascript
复制
require('electron').remote.getGlobal('sharedObject').someProperty = 'new value';

在第二个页面中

代码语言:javascript
复制
console.log(require('electron').remote.getGlobal('sharedObject').someProperty);

常见问题

jQuery/RequireJS/Meteor/AngularJS 的问题

jQuery 等新版本的框架,在 Electron 中使用普通的引入的办法会引发异常,原因是 Electron 默认启用了 Node.js 的 require 模块,而这些框架为了支持 commondJS 标准,当 Window 中存在 require 时,会启用模块引入的方式。

分别有以下几种解决方案:

方式一:

使用 Electron 官方论坛提供的方法,改变require的写法。下面的代码各个框架通用:

代码语言:javascript
复制
//在引入框架之前先输入下面的代码
<script>
	window.nodeRequire = require;
	delete window.require;
	delete window.exports;
	delete window.module;
</script>

方式二:

禁用Node.js的require模块化引入(如果你不想使用 Node.js 模块):

代码语言:javascript
复制
// In the main process.
let win = new BrowserWindow({
  webPreferences: {
   nodeIntegration: false
  }
});

方式三:

为使 web 项目正常浏览,在引入 jquery 后进行判断:

代码语言:javascript
复制
//置于引入 jQuery 之后
<script>
  if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};
</script>

关于页面跳转 的问题

在接收到命令后创建下一个窗口(创建窗口需要时间,期间可能出现空白):

代码语言:javascript
复制
//在main.js中::
const ipc = require('electron').ipcMain;
//进行监控,如果有new-window 发送过来,则重新创建一个窗口,文件是list.html
ipc.on('new-window', function () {
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, '/views/list.html'),
    protocol: 'file:',
    slashes: true
  }))
});

关于无边框窗口 的问题

为了使窗口无边框,使得在某些时候让项目看起来更美观,所以在创建窗口的时候通过设置 frame 属性的值为 false 来创建无边框窗口。

但是无边框窗口会产生无法移动的问题,对于这个问题我们可以在渲染进程中通过编辑 css 文件来解决。

设置 -webkit-app-region: no-drag 禁止拖拽:

代码语言:javascript
复制
body {
    -webkit-app-region: no-drag
}

需要拖拽的地方设置:

代码语言:javascript
复制
section {
    -webkit-app-region: drag;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 起步
  • 主进程和渲染进程
  • 主进程和渲染进程模块
    • 两种进程都可用的模块
      • Main Process 模块
        • Renderer Process 模块
        • 进程间通讯
          • 渲染进程=>主进程=>渲染进程
            • 主进程=>渲染进程
              • 渲染进程=>渲染进程
                • 使用全局共享属性
                • 利用主进程做消息中转
                • 使用 ipcRenderer.sendTo()
                • 利用 remote 接口直接获取渲染进程发送消息
                • 获取进程id的方法
            • 页面数据共享
            • 常见问题
              • jQuery/RequireJS/Meteor/AngularJS 的问题
                • 关于页面跳转 的问题
                  • 关于无边框窗口 的问题
                  相关产品与服务
                  云开发 CLI 工具
                  云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档