electron基础

教程很细很详细了,操作也很简单,可参考官方开发文档

个人理解来说,electron就是一个把html打包成桌面应用的框架,其内置了一个Chromium可以加载各种网页,以及可以在index.jspreload.js中执行nodejs代码。

其中在preload.js中可以主动暴露函数出来给前端代码调用,也可以通过postMessage向前端主动发送消息。=> 参考 添加preload.jspreload主动发送数据到前端

如果想给index.js中的内容发送到前端,那就需要先发到preload.js,再由preload.js发送给前端。 => 参考 注册全局快捷键


创建项目时可通过Electron Forge快速创建

npm init electron-app@latest my-app
cd my-app
npm install --save-dev electron

创建好的目录结构如下,可以说是应有尽有

image-20241020下午121752070

直接运行 npm run start 即可。

electron+vue3

项目搭建

先参考《vue项目搭建小结》搭建好vue的项目,能正常启动没问题后,执行如下命令添加electron,文档地址为 Vue CLI Plugin Electron Builder

vue add electron-builder

选择版本为最新的即可,安装好后执行如下命令即可启动!

# 启动
npm run electron:serve
# 打包
npm run electron:build

image-20241020下午13102236

其中 background.js 为electron的配置文件(index.js)。

image-20241020下午13339565

下面记录一些我用得比较多的

添加preload.js

vue.config.js中添加如下内容

module.exports = {
  pluginOptions: {
    electronBuilder: {
      preload: 'src/preload.js',
    }
  }
}

然后在src/background.js中添加如下内容

const path = require('path')
preload: path.join(__dirname, 'preload.js')

image-20241020下午25248466

最后在src目录下新建一个preload.js即可

编写代码测试一下:

const { contextBridge } = require('electron')
const {exec} = require('child_process')

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron
  // we can also expose variables, not just functions
})


function executeCommand(command) {
    return new Promise((resolve, reject) => {
        exec(command, (error, stdout, stderr) => {
            if (error) {
                reject(`执行错误: ${error}`);
                return;
            }
            resolve(stdout);
        });
    });
}

contextBridge.exposeInMainWorld('internal', {
    getWhoami: () => executeCommand('whoami'), // 执行系统命令whoami并返回结果
    getTest: function() {
        return "test"
    }
  })

image-20241020下午40317054

preload主动发送数据到前端

上面的例子是前端通过调用preload.js中的暴露函数实现的获取信息,那如果要主动给前端发数据呢?研究后发现通过postMessage发送数据会比较简单!

preload.js 中调用postMessage发送数据

const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('internal', {
    getTest: function() {
        window.postMessage({type:"hello", data:"hello post message"}, '*')
        return "test"
    }
  })

在vue接收数据的页面中监听message事件即可。

<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div>
</template>

<script>
export default {
  methods: {
    testEventListener(event) { // 监听到事件后执行的操作
      console.log(event)
      if (event.data.type === "hello") {
        console.log(event.data.data)
      }
    }
  },

  mounted() { // 注册message监听
    window.addEventListener('message', this.testEventListener)
  },
  unmounted() { // 一定要记得注销事件监听
    window.removeEventListener('message', this.testEventListener)
  },
}
</script>

效果如下:

image-20241020下午43237526

隐藏菜单

方式有很多,列举下面2个,在background.js中修改:

autoHideMenuBar: true, // 隐藏windows上面一排的菜单栏,mac上好像没用
frame: false, // 无边框

image-20241020下午43812947

注册全局快捷键

注册全局快捷键 option + I,任何地方按下后都会给展示页面随机设置值。(除了全局外还有当前应用的快捷键,可以根据实际情况来判定用哪一类,具体可参考键盘快捷键

实现流程:按下快捷键 -> 发送数据到preload.js -> preload.js发送数据到前端

1、按下快捷键,生成随机数并发送数据到preload.js

globalShortcut.register('Option+I', () => {
    let randomData = require('crypto').randomBytes(16).toString('hex')
    console.log(randomData)
    win.webContents.send('random', randomData)
})

image-20241020下午53520571

2、preload.js代码:接受数据,发送到前端

const { ipcRenderer } = require('electron')

ipcRenderer.on('random', (_event, value) => {
    window.postMessage({type: 'test', data: value}) // postMessage直接发给前端
})

3、前端展示

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <p>{{ randomString }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      randomString: null
    }
  },
  methods: {
    testEventListener(event) { // 监听到事件后执行的操作
      console.log(event)
      if (event.data.type === "test") {
        this.randomString = event.data.data
      }
    }
  },

  mounted() { // 注册message监听
    window.addEventListener('message', this.testEventListener)
  },
  unmounted() { // 一定要记得注销事件监听
    window.removeEventListener('message', this.testEventListener)
  },
}
</script>

这样每次按下快捷键后,前端的内容就会同步更改

image-20241020下午55458238

任务栏图标显示

使用Tray

const { Tray, Menu, nativeImage } = require('electron')

let tray
// 在 createWindow() 后
// const icon = nativeImage.createFromPath('src/assets/logo.png')
  const icon = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAn1JREFUOE+lkl9IU2EYxp/vnO3sH24gyTKJErGU0uG+TcRETSRE6I+aUSR0EUUoXahgN92EQUQUXiRdRBdFGWQgSmGZOcP8E5xzZkqQYVoYs5JZm5vbONv5YpEwYfOm9/J7v+cHz/M+BP85JFHvcDiKRFF0UweN5ZUL45455ZMSItawn93Xp6El5GdnCCH7RFEc3NBtAhSX0EmDmdsT8KrpWfu1CK7G8NujYmehRl2aiXKEg6o3EdfbUbE6KYBSagcgCUaCvEotLFYewV8qvs1G8fNzDBoBUCIsV5bl+aSA+COl9InBQhrDfgZCAMb+fSWAYCJvJkbFykTbmyzEF2UH7LdztqvNei0jxXsVDEzp0Fq/jq4+A/P6uf6xCbkuJYBSWmAxMbGtPiTMLPJ49k6HrguBuBi7rDEMSUJcWyhJ0mxSCzXV9tazh0K3bvQa0VAWgcfLYZuFYeqjBlea1vFwRIf3C/wd15i7OVWIrPlwCOMftCjMjoHnGB659Hh9zYe6zjScqozglSz09PRPn04JoLlRdLcEUNZuQa1TweoawYqPQ0QhuHgkhOtPje7BYTl+rb+zKURKKctMV1FlU7C0wkFlgF4A3PMaPO/04eAlC7Q8ll1j8o6kgKM1RZOl+UpJPKzey34cv2rGifII5j0cFr7zyDAzLP7g54Zccl5SQEWpva84P3os2xrDC0lAU1UYD4b1MOgYvD6CtoYwugd0XYMj061bFYnlZMYQCBF0NIbQcc+E87VhZJhVdD42MsaQJUnSckqA0+msUFV1tGB3dG32iybt5rkg2u+aQAhTVRW1siy/3LKJG0ubzZZl0nMneQHTwSD5mtj/RMAfdNUAIGhBEhMAAAAASUVORK5CYII=')
  tray = new Tray(icon)

  const contextMenu = Menu.buildFromTemplate([
    {
      label: '点击退出', 
      type: 'normal' , 
      click: () => { app.quit(); }
    }
  ])

  tray.setContextMenu(contextMenu) // 设置菜单
  tray.setToolTip('test') // 介绍
  tray.setTitle('d4m1ts') // 标题

image-20241020下午61559677

效果如下:

image-20241020下午61645418

打包图标生成

使用工具 electron-icon-builder 生成到 build/icons/ 目录下即可,打包时就会自动带上图标。

npm install -g electron-icon-builder
electron-icon-builder --input=./public/icon.png --output=./build --flatten

image-20241020下午72704185

打包后效果如下

image-20241020下午73219209

注意问题

打包异常

打包时记得填写上作者author和描述description字段。


如果出现错误 Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT

先执行 which python 找到 python2的路径,然后替换掉 /node_modules/dmg-builder/out/dmg.js 中的 "/usr/bin/python" 为查询到的真实的路径即可。

image-20241020下午71424947

打包后首页白板

serve显示正常,build后打开首页白板,即只显示了App.vue的内容,但是没显示其 <router-view/> 渲染的内容。

image-20241020下午73247110

解决办法也很简单,在 App.vue 中加一个首页跳转即可。

<script>
export default {
  mounted() {
    this.$router.push("/")
  },
}
</script>

这样再打开就一切正常了。

Copyright © d4m1ts 2023 all right reserved,powered by Gitbook该文章修订时间: 2024-10-20 19:48:31

results matching ""

    No results matching ""