electron学习笔记

#1. 简介

  • 官网
  • Electron是由GitHub众多开发者开发的一个开源项目,能够使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序

2. 五分钟快速上手

2.1 安装electron

初始化package.json文件

  • npm init

安装electron

  • cnpm I electron –S

2.2 配置为入口文件

{
  "name": "electron-demo",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "electron ."
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "electron": "^8.3.0"
  }
}

创建index.html

DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!title>
  head>
  <body>
    <h1>Hello World!h1>
  body>
html>

2.3 创建main.js文件

// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,//使用node模块及api
      contextIsolation: false,
      enableRemoteModule: true   // 使用remote模块
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.打开调试
  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. 也可以拆分成几个文件,然后用 require 导入。

2.4创建窗口

在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。 您可以通过使用 app.whenReady() API来监听此事件。 在whenReady()成功后调用createWindow()。app.whenReady()和app.on(‘ready’,()=>{})一样

app.on('ready', ()=>{
  const mainWindow = new 
  ({
    width: 800,
    height: 500
  })

  mainWindow.loadFile('index.html')
   app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

3. 自动刷新页面

  • 安装插件

    cnpm install --save-dev electron-reloader
    
  • 在入口引入插件

    const reloader = require('electron-reloader')
    reloader(module)
    

4. 主进程和渲染进程

Electron 运行 package.jsonmain 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程。

由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它的叫渲染进程的进程中。

在普通的浏览器中,web页面无法访问操作系统的原生资源。 然而 Electron 的用户在 Node.js 的 API 支持下可以在页面中和操作系统进行一些底层交互。

ctrl+shift+i打开渲染进程调试

默认打开调试

app.on('ready', ()=>{
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 500
  })

  mainWindow.loadFile('./index.html')

  const mainWindow2 = new BrowserWindow({
    width: 800,
    height: 500
  })
  
  mainWindow.webContents.openDevTools()

  mainWindow2.loadFile('./index2.html')
})

5. 自定义原生菜单

5.1 自定义菜单

详细文档:https://www.electronjs.org/docs/api/menu

const electron = require('electron')

const { app, Menu } = electron
const template = [
  {
    label: '文件',
    submenu: [
      {
        label: '新建窗口'
      }
    ]
  },
  {
    label: '编辑',
    submenu: [
      {
        label: '新建窗口'
      }
    ]
  }
]
const menu = Menu.buildFromTemplate(template)

Menu.setApplicationMenu(menu)

5.2 给菜单定义点击事件

1、点击打开新窗口

submenu: [
  {
    label: '新建窗口',
    click: ()=>{
      const newMainWindow = new BrowserWindow({
        width: 300,
        height: 300
      })
      newMainWindow.loadFile('./new.html')
    }
  }
]

2、点击打开浏览器

shell 模块提供了集成其他桌面客户端的关联功能.

const { BrowserWindow, Menu, shell } = require('electron')
const template = [
  {
    label: '文件',
    submenu: [
      {
        label: '文件1',
        click () {
          // 点击打开新窗口
          const mainWindow2 = new BrowserWindow({
            width: 600,
            height: 600
          })
        
          mainWindow2.loadFile('./index.html')
        }
      }
    ]
  },
  {
    label: 'csdn',
    click () {
      // 点击打开浏览器
      shell.openExternal('https://www.csdn.net/')
    }
  }
]

5.3 抽离菜单定义

const { BrowserWindow, Menu} = require('electron')
const template = [
  {
    label: '文件',
    submenu: [
      {
        label: '新建窗口',
        click: ()=>{
          const newMainWindow = new BrowserWindow({
            width: 300,
            height: 300
          })
          newMainWindow.loadFile('./new.html')
        }
      }
    ]
  },
  {
    label: '编辑',
    submenu: [
      {
        label: '新建窗口'
      }
    ]
  }
]
const menu = Menu.buildFromTemplate(template)

Menu.setApplicationMenu(menu)
require('./menu')
打开调式

mainWindow.webContents.openDevTools()

5.4 自定义顶部菜单

  • 通过frame创建无边框窗口

    const mainWindow = new electron.BrowserWindow({
        frame: false
    })
    
  • 自定义窗口

    <div class="custom-menu">
      <ul>
          <li>新建窗口li>
          <li>关于我们li>
        ul>
      div>
    
    * {
      margin: 0;
      padding: 0;
    }
    .custom-menu {
      height: 50px;
      width: 100%;
      background: pink;
    }
    
    .custom-menu ul {
      list-style: none;
    }
    
    .custom-menu ul li {
      float: left;
      width: 50px;
      line-height: 50px;
      text-align: center;
      margin-left: 10px;
    }
    

    添加-webkit-app-region: drag;实现拖拽

5.5 点击创建新窗口

// html
<li class="new-window">新建窗口</li>

// js
// remote 通过remote使用主进程的方法
const { remote: {BrowserWindow} } = require('electron')
const newWindow = document.querySelector('.new-window')
newWindow.onclick = function () {
  new BrowserWindow({
    width: 200,
    height: 300
  })
}

能够在html中使用node方法

const mainWindow = new BrowserWindow({
  width: 800,
  height: 500,
  webPreferences: {
    // 开启node模块
    nodeIntegration: true,
    // 开启remote模块
    enableRemoteModule: true
  }
})

5.6 点页面打开浏览器

  • html

    <a id="a1" href="https://www.itheima.com">打开浏览器a>
    
  • js

    const { shell } = require('electron')
    const allA = document.querySelectorAll('a')
    
    allA.forEach(item => {
      item.onclick = function (e) {
        e.preventDefault()
        console.log(item)
        shell.openExternal(item.href)
      }
    })
    

6. 打开对话框读取文件

6.1 读取文件

  • 定义点击事件

    <button onclick="openFile()">打开</button>
    
  • 定义事件函数

    打开对话框文档:https://www.electronjs.org/docs/api/dialog

    // 打开对话框
    function openFile() {
      const res = dialog.showOpenDialogSync({
        title: '选择文件',
        buttonLabel: '哈哈',
        filters: [
          { name: 'Custom File Type', extensions: ['js'] },
      ]
      })
    
      const fileContent = fs.readFileSync(res[0])
      dropEl.innerText = fileContent
    }
    

6.2 保存文件

  • 定义点击事件

    <button onclick="saveFile()">保存button>
    
  • 事件函数

    // 保存对话框
    function saveFile() {
      const res = remote.dialog.showSaveDialogSync({
        title: '保存文件',
        buttonLabel: '保存文件',
        filters: [
          { name: 'index', extensions: ['js'] },
        ]
      })
      fs.writeFileSync(res, dropEl.value)
    }
    

7. 定义快捷键

7.1 主线程定义

  • 引入

    const { app, BrowserWindow, globalShortcut } = require('electron')
    
  • 在ready中注册快捷键

    const ret = globalShortcut.register('CommandOrControl+X', () => {
      console.log('CommandOrControl+X is pressed + 打印结果在命令行')
    })
    
  • 定义快捷键最大、最小、关闭窗口

    globalShortcut.register('CommandOrControl+T',()=>{
        mainWindow.unmaximize();
      })
      globalShortcut.register('CommandOrControl+H',()=>{
        mainWindow.close()
      })
      globalShortcut.register('CommandOrControl+M',()=>{
        mainWindow.maximize()
      })
    

7.2 渲染进程定义

  • 通过remote注册

    // 定义快捷键
    remote.globalShortcut.register('Ctrl+O', () => {
      console.log('ctrl+o')
    })
    

8. 渲染进程和主线程通讯

  • 定义按钮

    <div class="maxWindow no-drag" onclick="maxWindow()">div>
    
  • 事件函数

    function maxWindow() {
      ipcRenderer.send('max-window')
    }
    
  • 主线程定义事件

    ipcMain.on('max-window', () => {
        mainWindow.maximize()
      })
    
  • 传参

    let windowSize = 'unmax-window'
    function maxWindow() {
      windowSize = windowSize === 'max-window' ?'unmax-window':'max-window'
      ipcRenderer.send('max-window',windowSize)
    }
    
  • 接收参数

    ipcMain.on('max-window', (event,arg) => {
        console.log(arg)
        if(arg === 'unmax-window') return mainWindow.maximize();
        mainWindow.unmaximize()
      })
    

09. electron打包

  • 安装electron-packager

    cnpm i electron-packager -D
    
  • 添加打包任务

    "build": "electron-packager ./ HelloWorld --platform=win32 --arch=x64 --out ./outApp --overwrite --icon=./favicon.ico"
    

10 .electron结合框架开发

  • 利用vue脚手架初始化项目

  • 在项目中安装electron

    cnpm i electron

  • 添加electron启动配置

    "main": "main.js",
    "scripts": {
       "start": "react-scripts start",
       "build": "react-scripts build",
       "test": "react-scripts test",
       "eject": "react-scripts eject",
       "electron": "electron ."
      },
    
  • 配置main.js

    const {app, BrowserWindow} = require('electron')
    
    function createWindow () {
      // Create the browser window.
      const mainWindow = new BrowserWindow({
        width: 800,
        height: 600
      })
      // Open the DevTools.
      // mainWindow.webContents.openDevTools()
    }
    
    app.on('ready', () => {
      createWindow()
    })
    
  • 加载vue项目

    mainWindow.loadURL('http://localhost:3000/')
    

其他

主进程可以使用的模块

app模块 : 控制整个应用的生命周期设计
autoUpdater模块 : 自动更新应用
BrowserWindow模块 : 创建一个浏览器窗口
contentTracing模块 : 收集由底层的Chromium content 模块 产生的搜索数据
dialog模块 : 提供一个弹出框或者文件选择框
globalShortcut模块 : 注册全局的自定义快捷键
ipcMain模块 : 提供主进程和渲染进程之间的通讯方法,接收渲染进程发射过来的事件和数据并进行回复
Menu模块 : 创建鼠票右键显示菜单,跟menuItem 模块配合使用 可以通过remote 模块给渲染的进程调用
powerSaveBlocker模块 : 阻止应用系统进入睡眠模式,允许应用保持系统和屏继续工作
session模块 : 创建一个新的Session对象,可为应用创建多个Cookie文件夹存储不同的数据信息,并且不会相互影响,积压自独立
webContents模块 : 是一个事件发出者,负责渲染并控制网页,也是BrowserWindow对象的属性,可设置打开调试窗口等。

渲染进程可以使用的模块

desktopCapturer 模块:获取可用资源,这个资源可以通过 getUserMedia 捕获得到
ipcRenderer 模块: 提供渲染进程之间的通试方法,可以从渲染进程向主进程发送同步或异步消息,也可以收到主进程相应
remote 模块: 使渲染进程可以调用主进程的模块
webFrame 模块 : 自定义如何渲染当前网页

两个进程都可以使用的模块

clipboard 模块: 提供方法来供复制和粘贴操作
crashReporter 模块: 开启发送应用崩溃报告,自动提交崩溃报告给服务器
nativeImage 模块: 图片对象,从剪切板中读取图片,它返回的是nativeImage
screen 模块: 屏幕的size,显示,鼠标位置等信息,即可根据用户显示器大小等信息进行渲染页面
shell 模块: 提供了集成其他桌面客端的关联功能,如果调用用户默认浏览器打开一个新窗口等

你可能感兴趣的:(electron学习笔记)