Electron神器

神奇的Electron

前言

今天經過技術核心、發展歷程、經常使用模塊三部份內容簡單的介紹一下Electron的身世。前端

技術核心

使用 JavaScript,HTML 和 CSS 構建跨平臺的桌面應用程序的開源架構git

1. Web技術

  • Electron 基於 Chromium 和 Node.js, 讓你能夠使用前端技術構建應用。
  • Electron = Chromium + Node.js + Native API

2. 開源

  • Electron 是一個由 GitHub 及衆多貢獻者組成的活躍社區共同維護的開源項目。

3. 跨平臺

  • Electron 兼容 Mac、Windows 和 Linux,能夠構建出三個平臺的應用程序。
  • macOS: 僅提供64位版本,而且只支持 macOS 10.10 (Yosemite) 以及更高版本。github

  • Windows: 僅支持 Windows 7 或更高版本, 舊版操做系統已再也不支持(而且沒法運行),提供了 ia32 (x86) 和 x64 (amd64) 兩種二進制版本。web

  • Linux:支持 Ubuntu 12.0四、Fedora 2一、Debian 8 及以上版本。Electron 的 ia32 (i686) 和 x64 (amd64) 預編譯版本均是在Ubuntu 12.04 下編譯的。chrome

發展歷程

  • 2013年4月11日,Electron以Atom Shell爲名起步。
  • 2014年5月6日,Atom以及Atom Shell以MIT許可證開源。
  • 2015年4月17日,Atom Shell更名爲Electron。
  • 2016年5月11日,1.0版本發佈。
  • 2016年5月20日,容許向Mac應用商店提交軟件包。
  • 2016年8月2日,支持Windows商店。
  • 2018年,2.0版本(5月2日),3.0版本(9月19日),4.0版本(12月21日)發佈。
  • 2019年,5.0版本(4月25日),6.0版本(7月30日),7.0版本(10月22日)發佈。
  • 2020年,8.0版本(2月4日),9.0版本(5月中旬)發佈。

進程通信

1. 主進程和渲染進程

Electron 中的 main.js 文件進程被稱爲主進程,在主進程中運行的腳本經過建立web頁面來展現用戶界面。一個 Electron 應用老是有且只有一個主進程。api

因爲 Electron 使用了 Chromium 來展現 web 頁面,因此 Chromium 的多進程架構也被使用到。 每一個 Electron 中的 web 頁面叫作渲染進程。瀏覽器

在普通的瀏覽器中,web頁面一般在沙盒環境中運行,而且沒法訪問操做系統的原生資源。 然而 Electron 的用戶在 Node.js 的 API 支持下能夠在頁面中和操做系統進行一些底層交互。markdown

2. 主進程和渲染進程之間的區別

主進程使用 BrowserWindow 實例建立頁面。 每一個 BrowserWindow 實例都在本身的渲染進程裏運行頁面。 當一個 BrowserWindow 實例被銷燬後,相應的渲染進程也會被終止。架構

主進程管理全部的web頁面和它們對應的渲染進程。 每一個渲染進程都是獨立的,它只關心它所運行的 web 頁面。app

在頁面中調用與 GUI 相關的原生 API 是不被容許的,由於在 web 頁面裏操做原生的 GUI 資源是很是危險的,並且容易形成資源泄露。 若是你想在 web 頁面裏使用 GUI 操做,其對應的渲染進程必須與主進程進行通信,請求主進程進行相關的 GUI 操做。

3. 代碼實例

  • 同步通信
// 渲染進程
    const { ipcRenderer } = require('electron')
    ipcRenderer.sendSync('synchronous-message', 'ping')

    // 主進程
    const { ipcMain } = require('electron')
    ipcMain.on('synchronous-message', (event, arg) => {
        console.log(arg) 
        event.returnValue = 'pong'
    })
複製代碼
  • 異步通信
// 渲染進程
    const { ipcRenderer } = require('electron')
    ipcRenderer.send('asynchronous-message', '我須要建立一個新窗口')

    // 主進程
    const { ipcMain } = require('electron')
    ipcMain.on('asynchronous-message', (event, arg) => {
        console.log(arg) 
        event.reply('asynchronous-reply', '好的,知道了')
    })

    // 渲染進程
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    	console.log('謝謝');
    })
複製代碼

經常使用模塊

app

  • 代碼舉例
const { app } = require('electron')
app.on('window-all-closed', () => {
  app.quit()
})

複製代碼

BrowserWindow

  • 代碼舉例
const { BrowserWindow } = require('electron')

let win = new BrowserWindow({ width: 800, height: 600 })
win.on('closed', () => {
  win = null
})

win.loadURL('https://github.com')
複製代碼

dialog

  • 代碼舉例
const { dialog } = require('electron') 

dialog.showMessageBox(mainWindow, {
            type: 'info',
            defaultId: 0,
            message: '您是否肯定如今退出?',
            buttons: ['退出','取消']
        })
複製代碼

Menu

  • 代碼舉例
const { Menu, MenuItem } = require('electron')

const menu = new Menu()
menu.append(new MenuItem({ label: 'MenuItem1', click() { console.log('item 1 clicked') } }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }))
複製代碼

desktopCapturer

  • 代碼舉例
// In the renderer process.
const { desktopCapturer } = require('electron')

desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
  for (const source of sources) {
    if (source.name === 'Electron') {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: false,
          video: {
            mandatory: {
              chromeMediaSource: 'desktop',
              chromeMediaSourceId: source.id,
              minWidth: 1280,
              maxWidth: 1280,
              minHeight: 720,
              maxHeight: 720
            }
          }
        })
        handleStream(stream)
      } catch (e) {
        handleError(e)
      }
      return
    }
  }
})

function handleStream (stream) {
  const video = document.querySelector('video')
  video.srcObject = stream
  video.onloadedmetadata = (e) => video.play()
}

function handleError (e) {
  console.log(e)
}

複製代碼

clipboard

  • 代碼舉例
const { clipboard } = require('electron')

clipboard.writeText('hello i am a bit of text!')

const text = clipboard.readText()
console.log(text)
// hello i am a bit of text!'
複製代碼

參考資料

相關文章
相關標籤/搜索