electron-vue 常规使用,通信、右下图标、快捷键设置

808 阅读3分钟

1. 创建electron-vue

安装vue-cli 在安装后使用使命

    // 项目的名字(不能有大写字母)
    // 使用vue命令创建 electron-vue 项目 
    vue init simulatedgreg/electron-vue 项目名称

例子:

1283956-20191213190843322-1548412017.png

  • sass需要的输入y
  • 下面axios、vue-electron、vue-router、vuex、vuex-electron这五项有不需要的就把光标移动到那一项,按空格
  • 键就会把 * 去掉。我这里没有安装后两项。然后按回车键接着进行下面的步骤。
  • 这里的ESLintwo和Karma+Mocha还有Spectron+Mocha我都没有安装,需要安装的写y(ESLint最好别安装要不然会让你很痛苦)

创建成功界面:

1283956-20191213194111558-1736013823.png

  • 项目创建完成后请用以下命令:
    // cd 到对应项目目录 如下:
    cd electorn-vue-demo
    // 查看目录中是否有安装好的插件,如没有请用以下命令安装(请务必安装 yarn) 关系到你项目能否正常启动:
    yarn 处始化项目  

当我们打开package.json 可以以下这些命令

    "build": "node .electron-vue/build.js && electron-builder",
    "build:dir": "node .electron-vue/build.js && electron-builder --dir",
    "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
    "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
    "dev": "node .electron-vue/dev-runner.js",
    "pack": "npm run pack:main && npm run pack:renderer",
    "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
    "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
    "postinstall": ""

运行项目: yarn dev 就可以了,打包用 yarn build

到这里项目基本搭建完成了

2. 引入所需要的UI

  • element-ui 引入
   // 使用命令安装 element-ui
   yarn add element-ui -S
   // 安装完成后在main.js 中引入
   import ElementUI from 'element-ui';
   import 'element-ui/lib/theme-chalk/index.css';
   Vue.use(ElementUI, {zIndex: 3000 });

这边我就不把所有的ui 引入方式 一一例举了,这边推荐常用的ui有:element-ui、iview、ant 我认为基本符合需求的ui。

3. electron-vue 结构通信处理

打开src/main 目录 我们会看到index.js 和 index.js 两个文件, 这边为了方便开发,这边对index.js进行了一些处理我这边给于分出了三个文件,分别是:

  • ipcMain.js
    import {ipcMain} from 'electron'

    // 与主进程进行通信
    const handleShowVersion = (win)=>{
        ipcMain.on('show-version',(event,data)=>{
            // event.sender.send 为发送实时消息
            win.send('show-message',data) 
            // 这里发信息给vue页面事件(是为了触发更新所预留的一个通信机制)
        })
    }

    export const onLoadIpc = (win)=>{
        handleShowVersion(win);
    }

  • 在App.vue 中创建接收事件做一些逻辑上的处理
    created() {
      // 接收主进程发来的消息
      this.$electron.ipcRenderer.on('show-message',(event,message) =>{
        console.log(message)
      })
    }
  • 在index.js 中的引用 在下文中所有的mainWindow 是创建项目,所自定义的窗口变量
    // 引入通信文件
    import {onLoadIpc} from './ipcMain'
    
    // 初始化对应的事件方法
    app.on('ready', ()=>{
      createWindow()
      // 初始化所有通信
      onLoadIpc(mainWindow)
    })

4. electron-vue 右下角图标设置

  • initTrayIcon.js
    import {Menu,Tray} from 'electron'
    //创建桌面角标
    export const  initTrayIcon=(win,app)=> {
        const tray = new Tray('build/icons/icon.ico');
        const trayContextMenu = Menu.buildFromTemplate([
            {
                label: '显示主窗口',
                click: () => {
                    win.show()
                }
            }, {
                label: '退出当前软件',
                click: () => {
                    app.quit()
                }
            }
        ]);
        tray.setToolTip('九为-收银台');
        // 右下角图标双击
        tray.on('double-click', () => {
            win.show()
        });
        // 右下角图标单击
        tray.on('click', () => {
            win.show()
        });
        // 右下角图标右击
        tray.on('right-click', () => {
            tray.popUpContextMenu(trayContextMenu);
        });
    }
  • 在index.js 中的引用
    // 引入通信文件
    import {initTrayIcon} from './initTrayIcon'
    
    // 初始化对应的事件方法
    app.on('ready', ()=>{
      createWindow()
      // 初始化所有通信
      onLoadIpc(mainWindow)
      // 设置右下角图标
      initTrayIcon(mainWindow,app)
    })

5. electron-vue 快捷键的设置

  • setGolbalShortcut.js
    import {globalShortcut} from "electron"

    export const handleSetShortcut = (win) =>{
        globalShortcut.register('F1+1',()=>{
            win.send('show-message','F1+1')
        })
    }
    export const handleUnloadShortcut = () =>{
        globalShortcut.unregisterAll()
    }
  • 在index.js 中的引用
    // 引入通信文件
    
    import {handleSetShortcut,handleUnloadShortcut} from './setGlobalShortcut'
    
    // 初始化对应的事件方法
    app.on('ready', ()=>{
      createWindow()
      // 初始化所有通信
      onLoadIpc(mainWindow)
      // 设置右下角图标
      initTrayIcon(mainWindow,app)
      // 设置全局快捷键
      handleSetShortcut(mainWindow)
   })
   
   app.on('window-all-closed', () => {
      if (process.platform !== 'darwin') {
        app.quit()
        // 卸载全局快捷键
        handleUnloadShortcut()
      }
   })
   
   // 关闭当前软件执行
   app.on('will-quit',  ()=>{
      // 卸载全局快捷键
      handleUnloadShortcut()
   })

6. electron-vue 热更新

这里申明一下:更新文件是我从网上找来的,这里我只是做一下 搬运工

    import { app, dialog} from 'electron'
    // 基础变量定义
    const request  = require('request')
    const { Notification  } = require('electron')
    const path = require('path');
    const fs = require('fs');
    const baseUrl = path.join(path.dirname(app.getPath('exe')) ,'./resources');
    const packageLocation =  `${baseUrl}/app/package.json`;
    const fileUrl = "http://www.tt.com/win32/";//这里需要修改为自己的资源外网
    var AdmZip = require('adm-zip');

    // 进度条
    const progress = require('progress-stream');
    const url = `${fileUrl}app.zip?v=${new Date().getTime()}`;


    // description

    export async function updateVersion(event) {
        const localpackage = await getLocalPackage(packageLocation);

        update(localpackage)


    }
    async function getLocalPackage(loc) {
        return new Promise(async (resolve,reject)=>{
            let existed = await isFileExisted(loc)
            let con = ''
            if (existed){
                con = fs.readFileSync(loc,'utf-8')
                resolve(con)
            }else{
                reject("err");
            }
        })

    }
    function isFileExisted(loc){
        return new Promise( (resolve, reject) => {
            fs.access(loc, (err) => {

                if (err) {
                    reject(false);
                } else {
                    resolve(true);
                }

            })
        })
    }



    function update(localpackage) {
        return new Promise((resolve, reject) => {
            request(
                {
                    url: `${fileUrl}package.json?v=${new Date().getTime()}`,//请求package.json,与本地对比版本号
                },
                (error, res, body) => {
                    console.log(body)
                    try {
                        if (error || res.statusCode !== 200) {
                            throw '更新版本号失败,请联系管理员';
                        }
                        const json = JSON.parse(body);
                        const { version, description } = json;
                        const localVersion = localpackage.version // 当前版本
                        console.log('版本号不一致')
                        if (version != localVersion) {
                            // mainWindow.webContents.send('updating', '更新中') //主线程给渲染线程
                            // 提示是否更新
                            showUpdate(description)

                        } else {

                        }
                    } catch (err) {
                        reject(err);
                    }
                })
        })
    }
    /**
     * download
     */
    function downLoad()  {
        return new Promise((resolve, reject) => {


            percentPost(url, 'www.tt.com','/win32/app.zip');

        })
    }
    function showUpdate(desc) {
        dialog.showMessageBox({
            type:'info',
            title:'新版本提示',
            message:desc,
            buttons:['现在更新','暂不更新'],
            cancelId: 1
        },function(index){
            if(index==0){
                console.log('update')
                const notification = {
                    title: '更新提醒:',
                    body: '正在静默更新,你可以继续你的操作!'
                    // silent:true
                }
                new Notification(notification).show()

                downLoad().then(() => {
                    updateNow();
                })
            }else if(index==1){
                console.log('wait')
            }
        })
    }

    function updateNow(){
        dialog.showMessageBox({
            type:'info',
            title:'更新完成提示',
            message:"更新完成,是否重启",
            buttons:['马上体验新版本','稍后体验'],
            cancelId: 1
        },function(index){
            if(index==0){
                app.relaunch();  // 重启
                app.quit();
            }else if(index==1){
                console.log('')
            }
        })
    }

    function percentPost(url,host,path) {
        var req = http.request(
            {
                host,
                path,
                method: "HEAD",
            },
            (res)=> {
                //显示进度条
                if (res.statusCode == 200) {
                    res.setEncoding(null);
                    var str = progress({
                        length: res.headers["content-length"],
                        time: 5 /* ms */,
                    });
                    str.on("progress", function (progress) {

                        var percentage = Math.round(progress.percentage).toFixed();
                        if(percentage<100){
                            //通知渲染线程同步
                            // global.eventValue.returnValue = percentage
                            // 通知渲染线程异步
                            global.percentage = percentage

                            global.eventValue.reply('show-percent',  percentage) // ELECTRON VERSION>5.0.13
                            // global.eventValue.sender.send('show-percent',percentage)

                        }
                    });
                    // request.get(url).pipe(str).pipe(fs.createWriteStream(`./di.zip`));
                    let reader = request.get(url).pipe(str).pipe(fs.createWriteStream(`${baseUrl}/di.zip`));
                    reader.on('close', () => {
                        console.log('开始解压')
                        const unzip = new AdmZip(`${baseUrl}/di.zip`);   //下载压缩更新包
                        unzip.extractAllTo(`${baseUrl}`, /*overwrite*/true);    //解压替换本地文件
                        console.log('覆盖成功');
                        resolve()
                    });
                } else {
                    console.log('err')
                }
            }
        );
        req.on("error", (e) => {
            console.log('err')
        });
        req.end();
    }

这里热更新文件对应的git的文件

gitee.com/lgpr/electr…

话不多说 到此结束