electron 研究笔记

使用electron有一阵子了,随着项目推进,需要研究的东西也逐渐多起来。总结了以下,问题主要出现在:
- 跨平台兼容性
- 新的功能需求


electron 渲染进程模拟浏览器环境

electron渲染进程默认为nodejs环境,在里面你可以调用require引入第三方模块,但有时候我们想要的是一个真实的浏览器环境。electron需要做的配置如下:


    var mainWindow = new BrowserWindow({
        resizable: true,
        width: size.width,
        height: size.height,
        title: 'HolaStudio',
        webPreferences:
        {
            nodeIntegration: false,
            preload: path.join(__dirname, 'tangide', 'expose-window-apis.js')
        }
    });

创建BrowserWindow的时候指定nodeIntegrationfalse。 这样在electron内置浏览器里面不会有modulerequire全局变量。


渲染进程与主进程之间的通信

electron下主进程与渲染进程之间的通信主要有如下几种方式:
- 使用remote模块
- 使用ipc做进程间通信

这里我选择了第二种方式:


// In main process.
const ipcMain = require('electron').ipcMain;
ipcMain.on('asynchronous-message', function(event, arg) {
  console.log(arg);  // prints "ping"
  event.sender.send('asynchronous-reply', 'pong');
});

ipcMain.on('synchronous-message', function(event, arg) {
  console.log(arg);  // prints "ping"
  event.returnValue = 'pong';
});

// In renderer process (web page).
const ipcRenderer = require('electron').ipcRenderer;
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"

ipcRenderer.on('asynchronous-reply', function(event, arg) {
  console.log(arg); // prints "pong"
});
ipcRenderer.send('asynchronous-message', 'ping');

在渲染进程引入模块,都需要用require的方式,但是按照要求,渲染进程必须是一个真实的浏览器环境,所以需要通过其他方式来引入模块包。

    preload: path.join(__dirname, 'tangide', 'expose-window-apis.js')

该配置的作用在于:

界面的其它脚本运行之前预先加载一个指定脚本. 这个脚本将一直可以使用 node APIs 无论 node integration 是否开启. 脚本路径为绝对路径。

expose-window-apis.js实现如下:

//inner process communication
window.ipc = require('electron').ipcRenderer;  

通过这种方式,渲染进程window对应引入了ipc模块,解决了渲染进程引入模块包的问题:)


mac系统下快捷键问题

Mac系统下,默认的快捷键RedoUndo、复制粘贴等不能使用,阅读了electron发现需要通过创建应用菜单的方式做一个映射。


const Menu = require("menu");
     // Create the Application's main menu
    let template = [{
        label: "Application",
        submenu: [
            { label: "About Application", selector: "orderFrontStandardAboutPanel:" },
            { type: "separator" },
            { label: "Quit", accelerator: "Command+Q", click: function() { app.quit(); }}
        ]}, {
        label: keysBinding["Edit"],
        submenu: [
            { label: keysBinding["Undo"], accelerator: "CmdOrCtrl+Z", selector: "undo:" },
            { label: keysBinding["Redo"], accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
            { type: "separator" },
            { label: keysBinding["Cut"], accelerator: "CmdOrCtrl+X", selector: "cut:" },
            { label: keysBinding["Copy"], accelerator: "CmdOrCtrl+C", selector: "copy:" },
            { label: keysBinding["Paste"], accelerator: "CmdOrCtrl+V", selector: "paste:" },
            { label: keysBinding["Select All"], accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
        ]}
    ];

//注册菜单  
Menu.setApplicationMenu(Menu.buildFromTemplate(template));

系统快捷键冲突问题

开发者最常用到的快捷键一个是F12,打开开发者工具。 F5刷新当前网页:

const globalShortcut = require('global-shortcut');   
registerShortcut();  
function registerShortcut() {
    function doRegister(cmd, callback) {
        globalShortcut.register(cmd, callback);
    }

    let registed = globalShortcut.isRegistered('F12');
    if(registed) return;

    doRegister('F12', function() {
        let win = BrowserWindow.getFocusedWindow();
        if(!win) return;
        win.webContents.toggleDevTools();
        console.log("toggleDevTools F12");
    });

    doRegister('F6', function() {
        let win = BrowserWindow.getFocusedWindow();
        if(!win) return;
        win.webContents.toggleDevTools();
        console.log("toggleDevTools F6");
    });

    doRegister('F5', function() {
        let win = BrowserWindow.getFocusedWindow();
        if(!win) return;
        win.reload();
        console.log("refresh");
    });

    return;
}

正常情况下通过注册全局快捷键的方式能够满足绝大多数情况下的应用场景,但是使用过程中还是有如下问题:
- electron注册了快捷键后,系统默认浏览器无法通过快捷键触发调式工具。
- windows系统electron应用的F12按键无效。

对于windows系统F12无效问题,electron官方貌似也没有一个好的解决方案。一个讨论的帖子。

快捷键覆盖的问题,目前的解决办法如下:
监听blurfocus事件,在blur事件下注消快捷键,在focus下重新注册监听快捷键。

    mainWindow.on('blur', function() {
        let win = BrowserWindow.getFocusedWindow();
        if(win) return;
        globalShortcut.unregisterAll();
        console.log('blur');
    });

    mainWindow.on('focus', function() {
        registerShortcut();
        console.log('focus');
    });

一个electron应用可能存在多个窗口,所以在主窗口触发blur事件的时候需要判断是不是所有electron都失去了焦点。 在这种情况下注消快捷键,以便系统浏览器能正常调式。

你可能感兴趣的:(Nodejs)