electron-vue開發問題總結


1.Electron 12中的remote模塊已棄用,將在Electron 14中拆除.由@electronic/remote 模塊替代

npm install --save @electron/remote
在主線程中使用:
注意:主進程要進行如下設置
     webPreferences: {
            nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false
            contextIsolation: process.env.ELECTRON_NODE_INTEGRATION,
            enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION,
        }
require(’@electron/remote/main’).initialize()// 開啟。這個必須得有。否則也創建不了
require("@electron/remote/main").enable(webContents)

    示例:

'use strict'

import {
    app,
    protocol,
    BrowserWindow,
    ipcMain,
    Menu,
    Tray
} 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'
const path = require('path');
require('@electron/remote/main').initialize()


// 在應用程序准備就緒之前,必須注冊方案
protocol.registerSchemesAsPrivileged([{
    scheme: 'app',
    privileges: {
        secure: true,
        standard: true
    }
}])
let mainWindow = null
let tray = null /******* 創建系托盤 *******/
let CreateTray =
    () => {
        tray = new Tray(path.join(__static, 'img/app.png'));
        const contextMenu = Menu.buildFromTemplate([{
                label: '設置',
                click: () => {} //打開相應頁面
            },
            {
                label: 'Item1',
                type: 'radio'
            },
            {
                label: 'Item2',
                type: 'radio',
                checked: true
            },
            {
                label: '退出',
                click: () => {
                    if (!!mainWindow) {
                        mainWindow.destroy()
                        mainWindow
                            = null
                    }
                    if (!!DesktopToolWindow) {
                        DesktopToolWindow.destroy()
                        DesktopToolWindow
                            = null
                    }
                }
            }, //我們需要在這里有一個真正的退出(這里直接強制退出)
        ])
        tray.setToolTip('My托盤測試')
        tray.setContextMenu(contextMenu)
        tray.on('click', () => { //我們這里模擬桌面程序點擊通知區圖標實現打開關閉應用的功能
            console.log("mainWindow.isVisible(", mainWindow.isVisible()) //isMinimized()
            mainWindow.show()

        })

    }
async function createWindow() {
    // 創建瀏覽器窗口。
    mainWindow = new BrowserWindow({
        width: 710,
        height: 492,
        resizable: false,
        frame: false,
        transparent: false,
        webPreferences: {
            nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false
            contextIsolation: process.env.ELECTRON_NODE_INTEGRATION,
            enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION,
        }
    })
    mainWindow.setSkipTaskbar(false)
    mainWindow.flashFrame(true)

    console.log("process.env.WEBPACK_DEV_SERVER_URL", process.env.WEBPACK_DEV_SERVER_URL)
    if (process.env.WEBPACK_DEV_SERVER_URL) {
        // 如果處於開發模式,請加載開發服務器的url
        await mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
        if (!process.env.IS_TEST) mainWindow.webContents.openDevTools()
    } else {
        createProtocol('app')
            // 加載索引,非開發中的html
            //mainWindow.loadURL('app://./index.html')
        mainWindow.loadURL('app://./index.html')
    }
    mainWindow.once("ready-to-show", () => {
            mainWindow.show();
        })
        // mainWindow.setMenu(null)


    /******* 引入遠程模塊 *******/
    require("@electron/remote/main").enable(mainWindow.webContents);

    mainWindow.on('closed', (event) => {
        mainWindow = null;

    });

    // mainWindow.on('close', (event) => {
    //     event.preventDefault();

    // });
    // mainWindow.on('show', (event) => {
    //     event.preventDefault();

    // })
    // mainWindow.on('hide', (event) => {
    //         event.preventDefault();

    //     })
}

// 關閉所有窗口后退出。
app.on('window-all-closed', () => {
    // 在macOS上,應用程序及其菜單欄很常見
    // 在用戶使用Cmd+Q明確退出之前保持活動狀態
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

app.on('activate', () => {
    //在macOS上,當
    //已單擊停靠圖標,並且沒有其他窗口打開。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

//此方法將在Electron完成后調用
//初始化並准備好創建瀏覽器窗口。
//某些API只能在此事件發生后使用。
app.on('ready', async() => {
    if (isDevelopment && !process.env.IS_TEST) {
        // 安裝視圖開發工具
        try {
            //await installExtension(VUEJS_DEVTOOLS)
        } catch (e) {
            console.error('Vue Devtools failed to install:', e.toString())
        }
    }
    createWindow()

    /******* 創建系托盤 *******/
    CreateTray()
        /******* 監聽渲染進程通信 *******/
    ipcMain.on('HomePage', (event, arg) => {
        console.log(arg)
        DesktopTool()
        mainWindow.resizable = true
        mainWindow.transparent = false
        mainWindow.minimize();
        event.reply('HomePage-reply', "我是主進程傳過去的參數")
    })

    ipcMain.on('DesktopTool', (event, arg) => {
            console.log(arg)
            mainWindow.resizable = true
            mainWindow.transparent = false
            mainWindow.show();
            event.reply('DesktopTool-reply', "我是主進程傳過去的參數")
        })
        //
    ipcMain.on('CloseClick', (event, arg) => {
        console.log(arg)
        mainWindow.resizable = true
        mainWindow.transparent = false
        mainWindow.minimize();
        event.reply('CloseClick-reply', "我是CloseClick-reply傳過去的參數")
    })

})

// 在開發模式下,根據父進程的請求干凈地退出。
if (isDevelopment) {
    if (process.platform === 'win32') {
        process.on('message', (data) => {
            if (data === 'graceful-exit') {
                app.quit()
            }
        })
    } else {
        process.on('SIGTERM', () => {
            app.quit()
        })
    }
}

/******* 以下是渲染進程 *******/ // 開啟DesktopToolWindow新窗口
let DesktopToolWindow = null

function DesktopTool() {

    if (!!DesktopToolWindow) {
        DesktopToolWindow.show()
    } else {
        CreateDesktopToolWindow()
    }
}

async function CreateDesktopToolWindow() {
    DesktopToolWindow = new BrowserWindow({
        width: 160,
        height: 160,
        parent: null,
        resizable: false,
        frame: false,
        transparent: true,
        alwaysOnTop: true,
        webPreferences: {
            nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false
            contextIsolation: process.env.ELECTRON_NODE_INTEGRATION,
            enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION,
        }
    })
    if (process.env.WEBPACK_DEV_SERVER_URL) {
        // 如果處於開發模式,請加載開發服務器的url
        await DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool')
            // if (!process.env.IS_TEST) //DesktopToolWindow.webContents.openDevTools()
    } else {
        createProtocol('app')
            // 加載索引,非開發中的html
        await DesktopToolWindow.loadURL('app://./index.html#/ztdada/desktoptool')
            //await DesktopToolWindow.loadURL("https://bilibili.com/")
    }

    // DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool');
    DesktopToolWindow.setIgnoreMouseEvents(false)
    DesktopToolWindow.setSkipTaskbar(true)
        // DesktopToolWindow.loadURL("https://bilibili.com/")
        //DesktopToolWindow.loadFile('../src/pages/DesktopToolPage/index.vue')
    DesktopToolWindow.on('closed', () => {
        DesktopToolWindow = null
    })



}

在渲染進程使用(.vue文件):

注意:在vue文件中直接require("electron")會報錯,需要這樣引入

const { require } = window;
const { ipcRenderer } = require("electron");
const { BrowserWindow } = require("@electron/remote");

或者這樣引入

const { ipcRenderer } =  window.require("electron");
const { BrowserWindow } =  window.require("@electron/remote");

    示例:

<script>
const { require } = window;
const { ipcRenderer } = require("electron");
const { BrowserWindow } = require("@electron/remote");
export default {
  name: "HomePage",
  mounted() {
    ipcRenderer.on("HomePage-reply", (event, arg) => {
      console.log(arg);
    });
  },
  methods: {
    RenderClick() {
      ipcRenderer.send("HomePage", "我是子進程傳過去的參數");
    },
  },
};
</script>

 2.@electron/remote經過上面配置在開發環境可以正常使用,但打包時,還需做以下配置,否則打包后運行軟件會報錯

官網上是這樣解釋:

本機模塊受支持,並且應在不進行任何配置的情況下工作,前提是啟用了節點集成。如果出現錯誤,可能需要將本機依賴項設置為外部網頁包(打開新窗口)。應該會自動找到它,但可能不會。為此,請使用externals選項. 

https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/guide.html#table-of-contents

 externals: ['@electron/remote'],
 nodeModulesPath: ['../../node_modules', './node_modules'],

在vue.config.js文件中:

  pluginOptions: {
        'style-resources-loader': {
            preProcessor: 'scss',
            patterns: [path.resolve(__dirname, './src/assets/globalscss/*.scss'), ]
        },
        electronBuilder: {
            externals: ['@electron/remote'],
            nodeModulesPath: ['../../node_modules', './node_modules'],
            builderOptions: {
                productName: "volodya",
                appId: 'volodya',
                win: {
                    "target": [
                        "nsis"
                    ],
                    icon: 'src/assets/img/app.png',
                    "requestedExecutionLevel": "requireAdministrator",
                    'legalTrademarks': 'http://www.baidu.com/'
                },
                "nsis": {
                    "installerIcon": "src/assets/ico/app.ico",
                    "uninstallerIcon": "src/assets/ico/app.ico",
                    "uninstallDisplayName": "CPU Monitor",
                    "license": "src/assets/ico/license.html",
                    "oneClick": false,
                    "allowToChangeInstallationDirectory": true,
                    "displayLanguageSelector": true,

                },
                "mac": {
                    "icon": "src/assets/ico/app.icns", // 應用程序圖標
                    "artifactName": "volodya", // 應用程序包名
                    "target": [
                        "dmg",
                        "zip"
                    ]
                },
                'dmg': {
                    'title': 'volodya',
                    'icon': 'src/assets/ico/app.icns',
                    'contents': [{
                            'x': 110,
                            'y': 150
                        },
                        {
                            'x': 240,
                            'y': 150,
                            'type': 'link',
                            'path': '/Applications'
                        }
                    ],
                    'window': {
                        'x': 400,
                        'y': 400
                    }
                }
            },
        },
    },

 3.在創建windows系統托盤時,let tray = null要設置為全局變量,否則會被回收機制清除,導致系統托盤自動消失的問題。

注意: __dirname=== dist_electron ,__static === public,例如:app.png圖片在vue-cli4創建的vue項目的public/img

文件下,在electron項目里使用 path.join(__static, 'img/app.png')

 

示例:

/******* 創建系托盤 *******/
let tray = null 
let CreateTray =
    () => {
        tray = new Tray(path.join(__static, 'img/app.png'));
        const contextMenu = Menu.buildFromTemplate([{
                label: '設置',
                click: () => {} //打開相應頁面
            },
            {
                label: 'Item1',
                type: 'radio'
            },
            {
                label: 'Item2',
                type: 'radio',
                checked: true
            },
            {
                label: '退出',
                click: () => {
                    if (!!mainWindow) {
                        mainWindow.destroy()
                        mainWindow
                            = null
                    }
                    if (!!DesktopToolWindow) {
                        DesktopToolWindow.destroy()
                        DesktopToolWindow
                            = null
                    }
                }
            }, //我們需要在這里有一個真正的退出(這里直接強制退出)
        ])
        tray.setToolTip('My托盤測試')
        tray.setContextMenu(contextMenu)
        tray.on('click', () => { //我們這里模擬桌面程序點擊通知區圖標實現打開關閉應用的功能
            console.log("mainWindow.isVisible(", mainWindow.isVisible()) //isMinimized()
            mainWindow.show()

        })

    }

調用:

CreateTray()

 4.vue,router,electron結合使用

注意:路由要用hash模式,不可用history模式

router/index.js

/**
 * Модуль роутера приложения
 */

import Vue from 'vue';
import VueRouter from 'vue-router';
import initListners from './initListners';
import listners from './listners';
import Home from '@/views/Home/index'
Vue.use(VueRouter)

const routes = [
    /* {
        path: '/',
        redirect: '/ztdada/home',
    }, */
    {
        path: '/ztdada/login',
        name: 'Login',
        component: () =>
            import ('@/views/Login/index'),
        meta: {
            Title: "登錄",

        }

    }, {
        path: '/',
        name: 'Home',
        component: Home,
        // component: () =>
        //     import ('@/views/Home/index'),
        meta: {
            Title: "首頁",

        }
    }, {
        path: '/ztdada/desktoptool',
        name: 'DesktopTool',
        component: () =>
            import ('@/views/DesktopTool/index'),
        meta: {
            Title: "首頁",

        }
    }, {
        path: '*',
        component: () =>
            import ('@/views/Error/index'),
        hidden: true
    }
];

const router = new VueRouter({
    // mode: 'history',
    // base: process.env.BASE_URL,
    routes
})

export default initListners(router, listners);

在electron項目中使用:

background.js

“/”根路徑頁面"http://192.168.252.1:8080/#/"使用

if (process.env.WEBPACK_DEV_SERVER_URL) {
        // 如果處於開發模式,請加載開發服務器的url
        await mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
        if (!process.env.IS_TEST) mainWindow.webContents.openDevTools()
    } else {
        createProtocol('app')
            // 加載索引,非開發中的html
            //mainWindow.loadURL('app://./index.html')
        mainWindow.loadURL('app://./index.html')
    }

路由頁面"http://192.168.252.1:8080/#/ztdada/desktoptool"使用

 if (process.env.WEBPACK_DEV_SERVER_URL) {
        // 如果處於開發模式,請加載開發服務器的url
        await DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool')
            // if (!process.env.IS_TEST) //DesktopToolWindow.webContents.openDevTools()
    } else {
        createProtocol('app')
            // 加載索引,非開發中的html
        await DesktopToolWindow.loadURL('app://./index.html#/ztdada/desktoptool')
            //await DesktopToolWindow.loadURL("https://bilibili.com/")
    }

示例:

'use strict'

import {
    app,
    protocol,
    BrowserWindow,
    ipcMain,
    Menu,
    Tray
} 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'
const path = require('path');
require('@electron/remote/main').initialize()

console.log(",__static, __dirname", __static, __dirname)
    // 在應用程序准備就緒之前,必須注冊方案
protocol.registerSchemesAsPrivileged([{
    scheme: 'app',
    privileges: {
        secure: true,
        standard: true
    }
}])
let mainWindow = null
let tray = null /******* 創建系托盤 *******/
let CreateTray =
    () => {
        tray = new Tray(path.join(__static, 'img/app.png'));
        const contextMenu = Menu.buildFromTemplate([{
                label: '設置',
                click: () => {} //打開相應頁面
            },
            {
                label: 'Item1',
                type: 'radio'
            },
            {
                label: 'Item2',
                type: 'radio',
                checked: true
            },
            {
                label: '退出',
                click: () => {
                    if (!!mainWindow) {
                        mainWindow.destroy()
                        mainWindow
                            = null
                    }
                    if (!!DesktopToolWindow) {
                        DesktopToolWindow.destroy()
                        DesktopToolWindow
                            = null
                    }
                }
            }, //我們需要在這里有一個真正的退出(這里直接強制退出)
        ])
        tray.setToolTip('My托盤測試')
        tray.setContextMenu(contextMenu)
        tray.on('click', () => { //我們這里模擬桌面程序點擊通知區圖標實現打開關閉應用的功能
            console.log("mainWindow.isVisible(", mainWindow.isVisible()) //isMinimized()
            mainWindow.show()

        })

    }
async function createWindow() {
    // 創建瀏覽器窗口。
    mainWindow = new BrowserWindow({
        width: 710,
        height: 492,
        resizable: false,
        frame: false,
        transparent: false,
        webPreferences: {
            nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false
            contextIsolation: process.env.ELECTRON_NODE_INTEGRATION,
            enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION,
        }
    })
    mainWindow.setSkipTaskbar(false)
    mainWindow.flashFrame(true)

    console.log("process.env.WEBPACK_DEV_SERVER_URL", process.env.WEBPACK_DEV_SERVER_URL)
    if (process.env.WEBPACK_DEV_SERVER_URL) {
        // 如果處於開發模式,請加載開發服務器的url
        await mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
        if (!process.env.IS_TEST) mainWindow.webContents.openDevTools()
    } else {
        createProtocol('app')
            // 加載索引,非開發中的html
            //mainWindow.loadURL('app://./index.html')
        mainWindow.loadURL('app://./index.html')
    }
    mainWindow.once("ready-to-show", () => {
            mainWindow.show();
        })
        // mainWindow.setMenu(null)


    /******* 引入遠程模塊 *******/
    require("@electron/remote/main").enable(mainWindow.webContents);





    mainWindow.on('closed', (event) => {
        mainWindow = null;

    });

    // mainWindow.on('close', (event) => {
    //     event.preventDefault();

    // });
    // mainWindow.on('show', (event) => {
    //     event.preventDefault();

    // })
    // mainWindow.on('hide', (event) => {
    //         event.preventDefault();

    //     })
}

// 關閉所有窗口后退出。
app.on('window-all-closed', () => {
    // 在macOS上,應用程序及其菜單欄很常見
    // 在用戶使用Cmd+Q明確退出之前保持活動狀態
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

app.on('activate', () => {
    //在macOS上,當
    //已單擊停靠圖標,並且沒有其他窗口打開。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

//此方法將在Electron完成后調用
//初始化並准備好創建瀏覽器窗口。
//某些API只能在此事件發生后使用。
app.on('ready', async() => {
    if (isDevelopment && !process.env.IS_TEST) {
        // 安裝視圖開發工具
        try {
            //await installExtension(VUEJS_DEVTOOLS)
        } catch (e) {
            console.error('Vue Devtools failed to install:', e.toString())
        }
    }
    createWindow()

    /******* 創建系托盤 *******/
    CreateTray()
        /******* 監聽渲染進程通信 *******/
    ipcMain.on('HomePage', (event, arg) => {
        console.log(arg)
        DesktopTool()
        mainWindow.resizable = true
        mainWindow.transparent = false
        mainWindow.minimize();
        event.reply('HomePage-reply', "我是主進程傳過去的參數")
    })

    ipcMain.on('DesktopTool', (event, arg) => {
            console.log(arg)
            mainWindow.resizable = true
            mainWindow.transparent = false
            mainWindow.show();
            event.reply('DesktopTool-reply', "我是主進程傳過去的參數")
        })
        //
    ipcMain.on('CloseClick', (event, arg) => {
        console.log(arg)
        mainWindow.resizable = true
        mainWindow.transparent = false
        mainWindow.minimize();
        event.reply('CloseClick-reply', "我是CloseClick-reply傳過去的參數")
    })

})

// 在開發模式下,根據父進程的請求干凈地退出。
if (isDevelopment) {
    if (process.platform === 'win32') {
        process.on('message', (data) => {
            if (data === 'graceful-exit') {
                app.quit()
            }
        })
    } else {
        process.on('SIGTERM', () => {
            app.quit()
        })
    }
}

/******* 以下是渲染進程 *******/ // 開啟DesktopToolWindow新窗口
let DesktopToolWindow = null

function DesktopTool() {

    if (!!DesktopToolWindow) {
        DesktopToolWindow.show()
    } else {
        CreateDesktopToolWindow()
    }
}

async function CreateDesktopToolWindow() {
    DesktopToolWindow = new BrowserWindow({
        width: 160,
        height: 160,
        parent: null,
        resizable: false,
        frame: false,
        transparent: true,
        alwaysOnTop: true,
        webPreferences: {
            nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false
            contextIsolation: process.env.ELECTRON_NODE_INTEGRATION,
            enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION,
        }
    })
    if (process.env.WEBPACK_DEV_SERVER_URL) {
        // 如果處於開發模式,請加載開發服務器的url
        await DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool')
            // if (!process.env.IS_TEST) //DesktopToolWindow.webContents.openDevTools()
    } else {
        createProtocol('app')
            // 加載索引,非開發中的html
        await DesktopToolWindow.loadURL('app://./index.html#/ztdada/desktoptool')
            //await DesktopToolWindow.loadURL("https://bilibili.com/")
    }

    // DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool');
    DesktopToolWindow.setIgnoreMouseEvents(false)
    DesktopToolWindow.setSkipTaskbar(true)
        // DesktopToolWindow.loadURL("https://bilibili.com/")
        //DesktopToolWindow.loadFile('../src/pages/DesktopToolPage/index.vue')
    DesktopToolWindow.on('closed', () => {
        DesktopToolWindow = null
    })



}
生產環境中electron加載路由頁面

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM