electron 学习笔记(一)

2017-07-24  本文已影响557人  sunner168

最近稍稍试了一下electron体验了一波简易开发桌面应用,将之前写的一个create-react-app改造成electron 应用,同时希望在学习electron的时候进一步加深对nodejs的了解
关于如何将一个create-react-app改造成一个electron-create-react-app
参考此文🌰
关于将electron热启加入到其中 我的例子

关于electron 目录组织的方式参考
关于electron的安全性问题

开发者能抵御这种逆向分析的手段也很有限——仅有混淆一途,而且效果也不佳,只要逆向者肯花点时间去分析,还是能够轻松逆向出源码。这也就注定了Electron只适合开源生态的程序的开发,并不适合对技术及知识产权的保护有强需求的企业和个人。
来源52破解

electron主要由两部分构成,一部分是chrome的环境,另外一部分就是集成的v8node环境。chrome环境最核心为electron提供了view的功能,就是展示网页,以及浏览器环境的api。而node提供了与电脑系统交互的环境,包括使用fs模块由或者是调用http。
关于node这里使用了一下深入nodejs的图片

15008583474714.jpg

再进一步看,包括解析javascript语法,以及调用libuv进行io操作等等

了解electron工作模式

 在源码阅读的发现充满着大量的观察者模式的运用,需要稍微了解一下什么是观察者模式下的订阅与发布。

从窗体打开到窗体通讯原理

在electron中,整体依托的是main进程,通过执行main进程打开窗体,在执行main进程的时候,我的理解是就跟打开一个新的进程.

//main.js
function createWindow () {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 500,
    'web-preferences': {'web-security': false}
  })

  /*log pid*/
  console.log(`Pid is ${process.pid}`)

  // dev mode load the localhost and pro load the build folder file
  const startUrl = process.env.ELECTRON_START_URL || url.format({
            pathname: path.join(__dirname, '/../build/index.html'),
            protocol: 'file:',
            slashes: true
    });
    mainWindow.loadURL(startUrl);

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })
}
app.on('ready', ()=>{
  //main window
  createWindow()
})
/*
browser-window:
https://github.com/electron/electron/blob/master/lib/browser/api/browser-window.js
*/

const {BrowserWindow} = process.atomBinding('window') 

...
 // Make new windows requested by links behave like "window.open"
  this.webContents.on('-new-window', (event, url, frameName,
    disposition, additionalFeatures,
    postData) => {
    const options = {
      show: true,
      width: 800,
      height: 600
    }
    ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
      event, url, frameName, disposition,
      options, additionalFeatures, postData)
  })

  this.webContents.on('-web-contents-created', (event, webContents, url,
    frameName) => {
    v8Util.setHiddenValue(webContents, 'url-framename', {
      url,
      frameName
    })
  })

  // Create a new browser window for the native implementation of
  // "window.open", used in sandbox and nativeWindowOpen mode
  this.webContents.on('-add-new-contents', (event, webContents, disposition,
    userGesture, left, top, width,
    height) => {
    let urlFrameName = v8Util.getHiddenValue(webContents, 'url-framename')
    if ((disposition !== 'foreground-tab' && disposition !== 'new-window') ||
      !urlFrameName) {
      return
    }

    let {
      url,
      frameName
    } = urlFrameName
    v8Util.deleteHiddenValue(webContents, 'url-framename')
    const options = {
      show: true,
      x: left,
      y: top,
      width: width || 800,
      height: height || 600,
      webContents: webContents
    }
    ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
      event, url, frameName, disposition, options)
  })
  ...

与新窗口的通信就是进程之间通信了,可以了解到不同窗口之间的通信就是要借助进程进行通信了.process对象对应的就是当前进程。在electron中是接触ipcMain与ipcRender进行渲染进程和主进程之间的通信,ipcMain与ipcRender.回到nodejs中进程通信是父子进程在(ipc)(Inter-process communication)上进行通信
所以先看一下process的文档中

process.send(message[, sendHandle[, options]][, callback])
/*If Node.js is spawned with an IPC channel, 
the process.send() method can be used to send messages 
to the parent process. Messages will be received as a 'message' 
event on the parent's ChildProcess object.
*/
//接受信息
process.on('message', function(args){
  
});

再结合nodejs进程通信🌰官方例子
这样就不难懂
ipcRender 中发送信息(直接理解成其是一个子进程与父进程Main通信)

//electron封装后的ipc api
ipcRenderer.send(channel[, arg1][, arg2][, ...])//异步信息发送
ipcRenderer.on(channel, listener)//监听信息
ipcRenderer.on(message,function(event,args){
   //...
})
ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])//同步信息发送

//electron中 ipcMain
ipcMain.on(channel, listener)
ipcMain.on(message,function(event,args){
  //event.sender(处理异步信息)
  //event.returnValue  
  //this to the value to be returned in a synchronous message.(用于处理同步信息)
})
上一篇下一篇

猜你喜欢

热点阅读