1

我正在研究使用 Ionic 4/ Capacitor 通过 Electron 选项来定位 Windows,用于我想使用 SQLite 的应用程序。

使用Ionic Native SQLite插件,它包装了这个 Cordova 插件,开箱即用,据我所见,Windows 支持 UWP,而不是桌面,它在 Ionic Capacitor 包装器中使用 Electron 运行。

我的计划是看看我是否可以使用Electron SQLite包,然后从我的 Ionic 应用程序中调用它,方法是为 Ionic 本机创建一个包装类,类似于我通过遵循本教程获得浏览器支持的方法

如果我可以从我的 Ionic 应用程序中调用 Electron 代码,那么我不明白为什么这不起作用。

所以,我的问题是,我可以调用代码(我将添加函数以使用 SQlite)从 Ionic(Web)代码中添加到托管 Electron 应用程序吗?如果是这样,怎么办?

提前感谢您的帮助

[更新1]

尝试了以下...

从 Ionic 页面,我有一个按钮单击处理程序,我在其中引发了一个事件..

export class HomePage {

 public devtools() : void {
  let emit = new EventEmitter(true);
  emit.emit('myEvent');

   var evt = new CustomEvent('myEvent');
   window.dispatchEvent(evt);
  }

然后在电子项目index.js中,我尝试了..

    mainWindow.webContents.on('myEvent', () => {
      mainWindow.openDevTools();
    });

    const ipc = require('electron').ipcMain
    ipc.on('myEvent', (ev, arg) => {
      mainWindow.openDevTools();
    });

但都没有奏效。

我应该提到我对 Electron 知之甚少。这是我第一次接触它(通过电容器)

4

2 回答 2

0

我昨天对此进行了深入研究,并为您提供了一个使用 angular 的示例(这也应​​该适用于 ionic)。在您的服务中声明要求,以便我们可以使用它

  //Below your imports
  declare function require(name:string);

然后在您想要使用它的任何功能中:

// Require the ipcRenderer so we can emit to the ipc to call a function
// Use ts-ignore or else angular wont compile
// @ts-ignore
const ipc = window.require('electron').ipcRenderer;
// Send a message to the ipc
// @ts-ignore
ipc.send('test', 'google');

然后在电子文件夹中创建的 index.js

// Listening for the emitted event
ipc.addListener('test', (ev, arg) => {
    // console.log('ev', ev);
    console.log('arg', arg);
});

它可能不是访问它的正确方法,但它是我能找到的最佳方法。据我了解,ipcRenderer 用于当您有多个浏览器在电子中相互交谈时。所以在我们的情况下,它使我们的 web 层能够与电子的东西进行通信

于 2019-04-19T16:48:59.040 回答
0

如果有人感兴趣,这就是我解决这个问题的方法。我正在使用 Ionic 4 / Capacitor + Vue 3。

在我的入口文件(app.ts)中,我声明了一个名为 Window 的全局接口,如下所示:

// app.ts
declare global { interface Window { require: any; } }

然后,我编写了以下类:

// electron.ts
import { isPlatform } from '@ionic/core';

export class Electron
{
    public static isElectron = isPlatform(window, 'electron');
    public static getElectron()
    {
        if (this.isElectron)
        {
            return window.require('electron');
        }
        else
        {
            return null;
        }
    }
    public static getIpcRenderer()
    {
        if (this.isElectron)
        {
            return window.require('electron').ipcRenderer;
        }
        else
        {
            return null;
        }
    }
    public static getOs()
    {
        if (this.isElectron)
        {
            return window.require('os');
        }
        else
        {
            return null;
        }
    }
}

我像这样使用它:

//electronabout.ts
import { IAbout } from './iabout';
import { Plugins } from '@capacitor/core';
import { Electron } from '../utils/electron';

export class ElectronAbout implements IAbout
{
  constructor() { }
  public async getDeviceInfo()
  {
    let os = Electron.getOs();
    let devInfo =
    {
      arch: os.arch(),
      platform: os.platform(),
      type: os.type(),
      userInfo: os.userInfo()
    };

    return devInfo;
  }
  public async showDeviceInfo()
  {
    const devInfo = await this.getDeviceInfo();
    await Plugins.Modals.alert({ title: 'Info from Electron', message: JSON.stringify(devInfo) });
  }
}

这是可行的,但当然,我仍然需要重构 Electron 类(electron.ts)。可能使用单例模式是一个更好的主意。

我希望这有帮助。

更新

您可以从渲染进程与您的主进程(index.js)进行通信,如下所示:

//somefile.ts
if (Electron.isElectron)
{
     let ipc = Electron.getIpcRenderer();
     ipc.once('hide-menu-button', (event) => { this.isMenuButtonVisible = false; });
 }

//index.js
let newWindow = new BrowserWindow(windowOptions);
newWindow.loadURL(`file://${__dirname}/app/index.html`);
newWindow.webContents.on('dom-ready', () => {
         newWindow.webContents.send('hide-menu-button');
         newWindow.show();
});
于 2019-09-04T13:50:07.413 回答