Быстро начните работу с Electron и получите собственное настольное приложение

Vue.js Electron
Быстро начните работу с Electron и получите собственное настольное приложение

предисловие

Сяолан обучениеelectronПричина в том, что курс создания программного обеспечения должен давать задание по программному обеспечению, а я не хочу его использовать.javaПишите, это не может быть веб-страница, первая мысль использоватьuniappНапишите проект, упакованный какAPP, тогда подумай об этом, продолжай слушатьelectronПервая страница (原生/h5/vue/react...), упакованный как настольное приложение, использующий интерфейсную страницу какGUIРазве это не оченьNice,Typoraто естьelectronЯ сделал это, мне было любопытно, поэтому я пошел учиться.Нижеследующее исследование Сяолана.electronЯ надеюсь, что это может немного помочь вам, изучаяelectronТут вроде бы много туториалов, но официальные документы относительно четкие и исчерпывающие.Возможно, то, что вы видели в видеоуроках, можно использовать.Когда вы сами набирали, вы обнаружили различные проблемы.Теперь...

1. Основное использование

Чтобы получить десктопное приложение, мы должны быстро в нем разобраться

1.1 Проблема с искажением терминала

tip: китайские искаженные иероглифы появляются, когда печать контролируется электроном.

image-20211004134055911

Просто запустите терминал (cmd)войтиchcp 65001Просто запусти

image-20211004134132071

1.2 Установка

// 如果没有node 的话先装 node
http://nodejs.cn/download/

// 在当前目录安装最新
npm i -D electron

// 全局安装最新
cnpm install electron -g

// 当然你可以指定版本号安装
npm i -D electron@11.0.4

node -v electron -vПроверьте, прошла ли установка успешно

1.3 Быстрое создание

начать создавать электрон

  • В первую очередь в каталоге должны быть:package.jsonэтот файл
  • Затем есть входной файл ниже этого примера, который я использую.index.jsНапример, но обычно записывается какmain.jsЛучше
  • По крайней мере, вам нужен интерфейс с графическим интерфейсом для отображения, обычно интерфейсная страница, или вы можете напрямую указать URL-адрес

Создайте новый каталог (проект):

инициализацияpackage.jsonдокумент

npm init

Не забудьте написать описание, этоelectronПри упаковке вспомнил, что нужно описание

начать писать команду"test": "nodemon --watch index.js --exec electron .", так что, наконец, введите в терминалnpm testПоэтому каждый раз, когда вы изменяетеindex.jsОсновной файл процесса перезапустит проект,index.jsМожно изменить самостоятельноmain.jsтак далее

приходите посмотреть последнийpackage.jsonфайл

// package.json 文件

{
  "name": "electron_demo",
  "version": "1.0.0",
  "description": "\"这是一个electron demo\"",
  "main": "index.js",
  "scripts": {
    "test": "nodemon --watch index.js --exec electron ."
  },
  "author": "",
  "license": "ISC"
}

У меня есть следующие файлы в моем каталоге

image-20211002115657083

electronна два процессаосновной процесса такжепроцесс рендеринга

index.jsЭтот файлосновной процесс

Официально так написано

const { app, BrowserWindow } = require('electron')

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

  // 并且为你的应用加载index.html
  win.loadFile('index.html')

  // 打开开发者工具
  win.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)

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

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

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

Я вижу, что другие люди пишут почти так же

const { app, BrowserWindow } = require('electron')
let win
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {
    // 创建一个窗口 设置属性
    win = new BrowserWindow({
    //fullscreen: true   //全屏
    //frame: false,   	//让桌面应用没有边框,这样菜单栏也会消失
    resizable: false,   //不允许用户改变窗口大小
    width: 800,         //设置窗口宽高
    height: 600,
    icon: iconPath,     //应用运行时的标题栏图标
    minWidth: 300,     // 最小宽度
    minHeight: 500,    // 最小高度
    maxWidth: 300,    // 最大宽度
    maxHeight: 600,    // 最大高度
    // 进行对首选项的设置
    webPreferences:{    
      backgroundThrottling: false,   //设置应用在后台正常运行
      nodeIntegration:true,     //设置能在页面使用nodejs的API
      contextIsolation: false,  //关闭警告信息
      //preload: path.join(__dirname, './preload.js')
    }
  })
  // 这里让主进程加载一个index.html
  win.loadFile('index.html')
  // 设置为最顶层
  //win.setAlwaysOnTop(true)
  //win.loadURL(`www.baidu.com`) 可以让主进程打开文件或者一个链接
  // 监听窗口关闭事件
  win.on('closed',()=>{
      //释放win
      win = null
  })
})

// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
    
    console.log('窗口全部都关闭了')
})

index.htmlдапроцесс рендерингаТо есть просто напишите что-нибудь на странице интерфейса, здесь интерфейс рассматривается как графический интерфейс.

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>electron test</title>
  </head>
  <body>
    electron demo
    <script></script>
  </body>
</html>

использовать вот такnpm testВы можете выйти с таким интерфейсом,testэта командаpackage.json scriptСредняя

image-20211003211108491

2.Удаленный модуль

в процессе рендеринга (например,index.htmlзагружен некоторымиjs-файл, тамjsЕсли вы хотите использоватьBrowserWindowЭти свойства необходимо использоватьremote)

использоватьremoteмодуль, вы можете позвонитьmain методы объекта процесса

2.1.electron14.0использовался в предыдущих версиях

Присоединяйтесь в окне основного процессаenableRemoteModule: trueпараметры для возможности вызова удаленного модуля

const { app, BrowserWindow } = require('electron')
app.on('ready', function () {
  let win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      //这里进行加入
      enableRemoteModule: true,
      nodeIntegration: true,
      contextIsolation: false,
    },
  })
  win.loadFile('index.html')
  // 监听所有的窗口都关闭了
  app.on('window-all-closed', () => {
    //释放win
    win = null
    console.log('窗口全部都关闭了')
  })
})

Тогда пишите в процессе рендеринга, здесь я напрямую встраиваю js

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>electron test</title>
  </head>
  <body>
    electron demo
    <button id="btn">添加新的窗口</button>
    <script>
      const { log } = console
      // 导入 remote 中的  BrowserWindow
      const { BrowserWindow } = require('electron').remote

      const btn = document.getElementById('btn')
      btn.onclick = () => {
        let newWin = new BrowserWindow({
          width: 800,
          height: 600,
        })
        // newWin.loadURL('www.baidu.com')
        win.loadFile('index2.html')

        newWin.on('close', () => {
          newWin = null
        })
      }
    </script>
  </body>
</html>

Нажмите кнопку здесь, чтобы снова создать новое окно

2.2.electron14.0Модификация версии API

Но здесь есть различие между версиями, и это меня долго беспокоило в начале... Наконец, я прочитал документ14.0Я изменил его позже, я использовал15. . .

image-20211003215043335

1. Вы должны установить его самостоятельноremote

npm i -D @electron/remote

2. Импорт в основной процесс

app.on('ready',function(){
	require('@electron/remote/main').initialize()
})

3. Во время рендеринга

//这样来引入remote
const { BrowserWindow } = require('@electron/remote') 

3. Создайте системное меню

1. Создайте новый menu.js

// 1.导入 electron 中的 Menu
const { Menu } = require('electron')

// 2.创建菜单模板,数组里的每一个对象都是一个菜单
const template = [
  {
    label: '菜单一',
    // submenu 代表下一级菜单
    submenu: [
      { 
          label: '子菜单一' ,
          // 添加快捷键
          accelerator: 'ctrl+n'
      },
      { label: '子菜单二' },
      { label: '子菜单三' },
      { label: '子菜单四' },
    ],
  },
  {
    label: '菜单二',
    // submenu 代表下一级菜单
    submenu: [
      { label: '子菜单一' },
      { label: '子菜单二' },
      { label: '子菜单三' },
      { label: '子菜单四' },
    ],
  },
]

// 3.从模板中创建菜单
const myMenu = Menu.buildFromTemplate(template)

// 4.设置为应用程序菜单
Menu.setApplicationMenu(myMenu)

accelerator: 'ctrl+n'Ярлыки могут быть назначены в меню

2. Напишите страницу небрежно

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>自定义菜单</title>
  </head>
  <body>
    自定义菜单
    <script></script>
  </body>
</html>

3. Напишите main.js

// 1.引入 electron
const { app, BrowserWindow } = require('electron')
// 定义一个窗口
let win = null
// 2.引入自定义的菜单
require('./menu')

// 3.监听ready
app.on('ready', function () {
  win = new BrowserWindow({
    width: 800,
    height: 600,
  })
  // 打开控制台
  win.webContents.openDevTools()
  win.loadFile('./index.html')
  // 4.监听窗口关闭事件
  win.on('close', () => {
    win = null
  })
})

запуск теста нпм

46

4. Добавьте события в меню

Например, добавьте событие клика в подменю, чтобы создать новое окно.

// 1.导入 electron 中的 Menu
const { Menu, BrowserWindow } = require('electron')

// 2.创建菜单模板,数组里的每一个对象都是一个菜单
const template = [
  {
    label: '菜单一',
    // submenu 代表下一级菜单
    submenu: [
      {
        label: '子菜单一',
        // 添加点击事件
        click: () => {
          // 创建一个新的窗口
          let sonWin = new BrowserWindow({
            width: 200,
            height: 200,
          })
          sonWin.loadFile('./index2.html')
          // 为关闭的时候进行清空
          sonWin.on('close', () => {
            sonWin = null
          })
        },
      },
      { label: '子菜单二' },
      { label: '子菜单三' },
      { label: '子菜单四' },
    ],
  },
  {
    label: '菜单二',
    // submenu 代表下一级菜单
    submenu: [
      { label: '子菜单一' },
      { label: '子菜单二' },
      { label: '子菜单三' },
      { label: '子菜单四' },
    ],
  },
]

// 3.从模板中创建菜单
const myMenu = Menu.buildFromTemplate(template)

// 4.设置为应用程序菜单
Menu.setApplicationMenu(myMenu)

визуализация

47

вышеупомянутые инструменты разработчика ихром/пограничный браузертак же, как в строке менюView -> Toggle Developer Tools,илиCtrl + Shift + IЕго можно вызвать для отладки страницы

5. Используйте модули/API Node.js

например, писатьчитать и писать файлыпример

Когда основной поток создает окноwebPreferencesдолжен добавитьnodeIntegration: true,contextIsolation: false

Это можно использовать в процессе рендерингаnodeнекоторый синтаксис

main.js

// 导入 electron
const { app, BrowserWindow } = require('electron')

let mainWindow = null

app.on('ready', () => {
  // // 新建一个窗口
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true, // 是否集成 Nodejs,把之前预加载的js去了,发现也可以运行
      contextIsolation: false,
    },
  })
  // 加载渲染文件
  mainWindow.loadFile('./main.html')
  // 窗口关闭后清空变量
  mainWindow.on('close', () => {
    mainWindow = null
  })
})

main.html основной файл рендеринга

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>读写文件测试</title>
  </head>
  <body>
    <button onclick="readFile()">读取文件</button>
    <button onclick="writeFile()">写入文件</button>
    <p id="show_file_content">页面内容</p>
    <script src="./index.js"></script>
  </body>
</html>

index.js загружает необходимые js

Видно, что в процессе рендерингаmain.htmlзагружен внутриindex.js, вы можете либо использоватьdocment.getElementByIdЭтиWebAPI, также можно использоватьnodeмодули для смешивания

// 导入 node 的模块
const fs = require('fs')
const path = require('path')
const { log } = console

// 获取到文件展示的dom
const showContent = document.getElementById('show_file_content')

// 读取文件
function readFile() {
  console.log('读取文件')
  fs.readFile(path.join(__dirname, '/test.txt'), (err, data) => {
    if (err) {
      throw new Error(err, '读取文件失败')
    }
    showContent.innerText = data
  })
}
// 需要写入的内容
const content = '今天是国庆的第二天,在学 electron'

// 写入文件
function writeFile() {
  fs.writeFile(
    path.join(__dirname, '/test.txt'),
    content,
    'utf8',
    (err, data) => {
      if (err) {
        return new Error(err, '读取文件失败')
      }
      log('写入文件成功')
    }
  )
}

txt для тестирования

今天是国庆的第二天,在学 electron

каталог проекта

image-20211002155537033

визуализация

45

6. Установите без полей

При создании окна можно было ставить без полей, и меню с ним исчезло.

let win = new BrowserWindow({
    frame: false,   	//让桌面应用没有边框,这样菜单栏也会消失
    width: 800,         //设置窗口宽高
    height: 600,
})

На самом деле меню все равно есть, все так же можно вызвать меню через горячие клавиши, можно удалить меню напрямуюwin.removeMenu()

Как перетаскивать окна без строки меню

В css вы можете установить, что можно перетаскивать/отключать.

Напримерbody{ -webkit-app-region: drag | no-drag;}

Рендеринг: без полей, вbodyустановить перетаскиваемый

44

7. Системный трей

image-20211004102538924

Когда вы видите приведенную выше картинку, всем должно быть понятно, когда мы закрываем приложение, оно на самом деле закрыто, но не полностью закрыто, а скрыто, а некоторые хранятся в системном трее, так какelectronКак насчет настройки системного трея?

Официальная документация: Трей

Основной процесс index.js

существуетelectronЗдесь я добавляю системный трей в начале, конечно можно создать трей когда окно закрыто

// 引入托盘 Tray,和 Menu 等下要创建菜单,nativeImage创建 icon图标
const { app, BrowserWindow, Tray, Menu, nativeImage } = require('electron')
const path = require('path')
let win, tray
app.on('ready', function () {
  win = new BrowserWindow({
    width: 800,
    height: 600,
  })
  // 创建icon我这里使用的是一个png
  const icon = nativeImage.createFromPath(
    path.join(__dirname, '/static/icon.png')
  )
  // 实例化一个 托盘对象,传入的是托盘的图标
  tray = new Tray(icon)
  // 移动到托盘上的提示
  tray.setToolTip('electron demo is running')
  // 还可以设置 titlle
  tray.setTitle('electron demo')

  // 监听托盘右键事件
  tray.on('right-click', () => {
    // 右键菜单模板
    const tempate = [
      {
        label: '无操作',
      },
      {
        label: '退出',
        click: () => app.quit(),
      },
    ]
    //通过 Menu 创建菜单
    const menuConfig = Menu.buildFromTemplate(tempate)
    // 让我们的写的托盘右键的菜单替代原来的
    tray.popUpContextMenu(menuConfig)
  })
  //监听点击托盘的事件
  tray.on('click', () => {
    // 这里来控制窗口的显示和隐藏
    if (win.isVisible()) {
      win.hide()
    } else {
      win.show()
    }
  })
  win.loadFile('index.html')
})
// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
  //释放win
  win = null
  console.log('窗口全部都关闭了')
})

визуализация

48

8. Межпроцессное взаимодействие

electronТребуется связь между основным процессом и процессом рендеринга

Официальная документация:

ipcMain

ipcRenderer

webContents

основной потокприбытьвизуализировать нитьпройти черезwebContents.sendотправить --->ipcRenderer.onконтролировать

визуализировать нитьприбытьосновной потокнужно пройтиipcRenderer.sendотправить --->ipcMain.onконтролировать

8.1. От основного процесса к процессу рендеринга

webContents.send(channel, ...args)

  • channel String
  • ...args any[]

основной процессmian.js

используется в основном процессеwebContents.sendотправлять сообщения

//主进程
const { app, BrowserWindow } = require('electron')
let win
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {
  // 创建一个窗口
  win = new BrowserWindow({
    width: 800, //设置窗口宽高
    height: 600,

    // 进行对首选项的设置
    webPreferences: {
      enableRemoteModule: true,
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  })
  // 发送给渲染线程
  setTimeout(() => {
    win.webContents.send('mainMsg', '我是主线程发送的消息')
  }, 3000)
  // 这里让主进程加载一个main.html
  win.loadFile('main.html')
})

// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
  //释放win
  win = null
  app.quit()
  console.log('窗口全部都关闭了')
})

процесс рендерингаmain.htmlодна внешняя ссылкаrender.js

использовать в потоке рендерингаipcRenderer.onконтролировать

ipcRenderer.on(channel, listener)

  • channel String
  • listener Function

мониторchannel, когда приходит новое сообщение, используйтеlistener(event, args...)передачаlistener .

Также есть сообщение, которое нужно прослушать один разipcRenderer.once(channel, listener)

Добавить одноразовый для этого событияlistenerфункция.listenerбудет в следующий раз, когда новое сообщение будет отправлено наchannelвызывается по запросу, а затем удаляется

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>通信测试</title>
  </head>
  <body>
    通信测试
    <p id="receive">接收信息</p>
    <script src="./render.js"></script>
  </body>
</html>

//渲染进程

//引入ipcRenderer
const electron = require('electron')
const { ipcRenderer } = require('electron')
const { log } = console

log(ipcRenderer)
ipcRenderer.on('mainMsg', (event, task) => {
  log(task)
  document.getElementById('receive').innerText = task
})

визуализация

49

8.2 Преобразование процесса в основной процесс

render.jsОтправить в поток рендерингаipcRenderer.send

ipcRenderer.send(channel[, arg1][, arg2][, ...])

  • channel String
  • arg(необязательный)

и отправлять синхронные сообщенияipcRenderer.sendSync(channel[, arg1][, arg2][, ...])

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>通信测试</title>
  </head>
  <body>
    通信测试
    <p id="receive">接收信息</p>
    <button onclick="sendMain()">发送消息给主线程</button>
    <script src="./render.js"></script>
  </body>
</html>

const electron = require('electron')
const { ipcRenderer } = require('electron')

//...

function sendMain() {
  ipcRenderer.send('task', '退出程序')
}

main.jsвнутри основного процессаipcMain.onМонитор, выход из программы здесь

ipcMain.on(channel, listener)

  • channel String
  • listener Function

мониторchannel, когда приходит новое сообщение, оно будет передано черезlistener(event, args...)передачаlistener.

Еще одинipcMain.once(channel, listener)Добавить одноразовое использование для событияlistenerфункция.listenerТолько когда приходит следующее сообщениеchannelвызывается по запросу, а затем удаляется.

const { app, BrowserWindow, ipcMain } = require('electron')
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {
  //...
})

ipcMain.on('task', (event, info) => {
  if (info === '退出程序') {
    app.quit()
  }
})

визуализация

50

Это делает удобным для меня некоторые взаимодействия с окном, такие какtodoList, когда придет время, в правом нижнем углу появится новое окно, чтобы напомнить

8.3 Процесс рендеринга за процессом рендеринга

ipcRenderer.sendTo(webContentsId, channel, ...args)

  • webContentsId Number
  • channel String
  • ...args any[]

пройти черезchannelотправить сообщениеwebContentsIdокно.

Предпосылка состоит в том, чтобы знать соответствующий процесс рендерингаID

Конечно, основной процесс также может использоваться как станция передачи, сначала направляемая в основной процесс, а затем в другие процессы рендеринга.

9.Vue + Electron

ТакVueкак использоватьElectronЧто насчет упаковки? Ведь первоначальная цель обучения состоит в том, чтобыVueПроект становится настольным приложением. Все предыдущие методы являются нативными, поэтому продолжайте смотреть ниже.

9.1 Вам нужен проект Vue

Если у вас его нет, то используйтеvue uiСоздаватьVueпроект/или непосредственно в командной строкеvue createСоздайте

vue ui

Я думаю, что все будут, здесь я просто используюvue uiчтобы построить один, вы можете пропустить его здесь

По умолчанию открывается служба порта 8000 и выходит визуальный UI-интерфейс.

image-20211005094817591

Выберите «Дополнительно» -> «Диспетчер проектов» в левом нижнем углу.

image-20211005095048918

Создайте

image-20211005095255377

После выбора каталога создайте его здесь

image-20211005095412222

Заполните основную информацию, управление пакетами здесь я использую npm, а затем следующий шаг.

image-20211005095517636

Выберите предустановку, здесь я выбираю вручную

image-20211005095738225

Какие плагины нужно выбрать, я буду здесь по умолчанию, потому что это простой пример

image-20211005095856488

Выберите версию Vue 2.x или 3. Это в соответствии с вашими привычками.Что вы обычно пишете, следующие варианты являются критериями, которые я выбираю

image-20211005100020344

Создать проект

Не буду тут сохранять пресеты, а то долго ждатьimage-20211005100221788

Запустить проект после создания

image-20211005102004448

Стартовый проект

image-20211005102132311

Вы получите страницу по умолчанию, подобную этой

image-20211005102159772

Хорошо, создание проекта завершено, продолжаем

9.2 Дополнениеelectronплагин

Поиск в плагинах-->Добавить плагинvue-cli-plugin-electron-builder, установить первый

image-20211005102527050

Я выбираю версию electron 13.0.0 по умолчанию здесь

image-20211005102834003

После завершения установки он появится в установленных плагинах.

image-20211005103108921

Конечно, вы также можете установить его из командной строки.

vue add electron-builder

9.3 Бег

Введите следующую команду в командной строке текущего проекта vue для запуска.

npm run electron:serve

image-20211005103731994

хорошо, работает

9.4 package.json background.js

Проверитьpackage.jsonГде находится файл, чтобы найти основной файл процесса

image-20211005104023792

image-20211005104135614

Основной файл процессаbackground.js, этот файл находится вVue项目/src/下面

'use strict'

import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: 'app', privileges: { secure: true, standard: true } }
])

async function createWindow() {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
    }
  })

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    win.loadURL('app://./index.html')
  }
}

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

app.on('activate', () => {
  // 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()
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      console.error('Vue Devtools failed to install:', e.toString())
    }
  }
  createWindow()
})

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', (data) => {
      if (data === 'graceful-exit') {
        app.quit()
      }
    })
  } else {
    process.on('SIGTERM', () => {
      app.quit()
    })
  }
}

Увидев вышеприведенный основной файл процесса, вы не очень знакомы, вы можете выполнять некоторые операции, как и раньше, используя микширование узлов для выполнения некоторых функций.

9.5 Упаковка

Выше мы его просто запустили, софт, который мы сдали, учитель не пойдет специально настраивать среду, а тоnpm run electron:serveНу явно нельзя, тогда продолжаем упаковывать в исполняемый файл exe

Командная строка выполняет следующую команду

npm run electron:build

проблемы с упаковкой

У меня действительно плохое время, когда я собираю вещи ... Проверьте этоelectronсуществует проблема

мое предложение поставитьnode_modulesв каталогеудаление электрона

использоватьcnpmУстановитьelectron

если нетcnpmУстановить первым

Установить глобальноcnpm

npm install -g cnpm --registry=https://registry.npm.taobao.org
# 查看是否安装成功了
cnpm -v

переустановитьelectron

cnpm i electron

Пакет

npm run electron:build

image-20211005131543735

После завершения упаковки упакованные файлы помещаются под проектdist_electronв

image-20211005131647326

9.6 Установка

Дважды щелкните для автоматической установки

image-20211005131805110

image-20211005131940327

На рабочем столе появляется значок приложения

image-20211005132041458

9.7 Настройка

Нет проблем с нажатием для проверки, но не слишком ли низко, автоматически устанавливается один клик, и используется значок по умолчанию

Установите инструмент для упаковки

cnpm i electron-builder --D

9.7.1 Сначала найдите одинiconкартина

Кажется, есть плагин, который может конвертировать изображения в различные размеры.icon

Установите его, чтобы вам не пришлось переносить картинки на сайт

cnpm i electron-icon-builder 

нуждаться вpackage.jsonсерединаscriptsДобавить кbuild-iconинструкция

longzhu.jpgЭто изображение было найдено Kakarot и может быть изменено вами самостоятельно.

outputПапки вывода


  "scripts": {
    "build-icon": "electron-icon-builder --input=./public/longzhu.jpg --output=build --flatten"
  },

ввод командной строки

npm run build-icon

image-20211005141605242

После завершения сборки генерируются изображения разных размеров

9.7.2.vue.config.js

Поскольку плагин, который мы установили ранее, былvue-cli-plugin-electron-builder, вместоelectron-builder

electron-builderупакуйте общие предметы,buildнастроить прямо вpackage.jsonнаписать внутри

vue-cli-plugin-electron-builderизbuildКонфигурация должна находиться в корневом каталоге проекта.vue.config.jsвнутренняя конфигурация

Если нет, создайте новый

module.exports = {
  pluginOptions: {
    electronBuilder: {
      builderOptions: {
        appId: "com.test.app",
        productName: "Lang", //项目名,也是生成的安装文件名,即aDemo.exe
        copyright: "Copyright © 2021", //版权信息
        directories: {
          output: "./dist" //输出文件路径
        },
        win: {
          //win相关配置
          icon: "./build/icons/icon.ico", //图标,当前图标在根目录下,注意这里有两个坑
          target: [
            {
              target: "nsis", //利用nsis制作安装程序,打包文件的后缀为exe
              arch: [
                "x64", //64位
                "ia32" //32位
              ]
            }
          ]
        },
        nsis: {
          oneClick: false, //一键安装
          language: "2052", //安装语言
          perMachine: true, //应用所有用户
          allowToChangeInstallationDirectory: true //用户可以选择路径
        }
      }
    }
  }
};

9.7.3 Выполнение упаковки

npm run electron:build

image-20211005143529020

Хорошо, упаковано успешно!

возможные проблемы

Путь к упаковке не был гладким, упаковка не удалась на этом этапе, потому что некоторые зависимости были загружены во время упаковки, а затем загрузка не удалась.

Решение 1. Лестница

Обходной путь 2:можно обратиться к этому

image-20211005143747806

упакованные вещи

Упакованные вещи размещаются в нашей прежней конфигурацииbuild output: "./dist"// путь к выходному файлу

image-20211005144321420

Видно, что иконка изменилась.

image-20211005144400797

Теперь мы можем настроить папку установки

image-20211005144559596

image-20211005144749686

Что ж, основная работа по упаковке окончена, вы можете написать свое собственное программное обеспечение, вот простое обучение работе с приложением.

Эпилог

ElectronЭто действительно хорошо. Я предлагаю вам читать больше официальных документов, когда вы изучаете. Хотя в официальных документах еще много мест, которые не были полностью переведены, это не влияет на наш энтузиазм в его изучении. Я чувствую, что итерация версии очень быстро, да и официальных документов много, муторно, можно поискать в документации

Электронная официальная документация

Прекрасное прошлое

Еще не Vue3? Заметка, чтобы взять вас быстро

Еще не ТС? Быстрый старт с TypeScript

Быстрый старт Vuex для рукописного ввода Easy Vuex

От понимания к глубокому виртуальному DOM и реализации алгоритма сравнения

Написание простого ответа vue поможет вам понять принцип ответа.

От использования до самостоятельной реализации простого Vue Router — просто взгляните на это

Необходимые базовые знания о фронтенд-интервью, хотя и немногочисленные, но вы не можете не знать