1.创建项目
# "vue": "^3.0.0"
vue create electron-learn
# "electron": "^13.0.0"
vue add electron-builder
yarn add three@0.134 troisjs
# "@electron/remote": "^2.0.9"
yarn add @electron/remote
2.项目构建
1.构建时出现依赖安装错误
yarn config set registry https://registry.npm.taobao.org
yarn config set electron_mirror https://npm.taobao.org/mirrors/electron/
yarn config set electron_builder_binaries_mirror https://npm.taobao.org/mirrors/electron-builder-binaries/
3.预加载代码
// src/preload.ts
import { contextBridge } from 'electron'
// import { remote } from 'electron'
import { createRightMenu } from '@/electron'
import { nativeImage, ipcRenderer } from 'electron'
const remote = require('@electron/remote')
const handler = createRightMenu()
contextBridge.exposeInMainWorld('electron', {
nativeImage,
remote,
ipcRenderer
})
// vue.config.js
{
"electronBuilder": {
preload: path.join(__dirname, 'src/preload.ts')
}
}
1.preload.ts - useage
在每个窗口构建时(即在渲染进程中通过 preload.ts
新开窗口)都需要注入预加载逻辑;
const win = new BrowserWindow({
width: 1024,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
contextIsolation: true,
nodeIntegration: true,
enableRemoteModule: true,
preload: path.join(__dirname, 'preload.js') // 给窗口注入预加载逻辑
}
})
4.编写全局声明文件
// src/global.d.ts
interface WinOpts {
payload?: Record<any, any>;
windows?: Record<any, any>;
route: string;
callback?: (data?: any) => void;
}
interface ElectronAPI {
remote: {
dialog: Electron.Dialog;
Menu: Electron.Menu;
shell: Electron.Shell;
MenuItem: Electron.MenuItem;
};
ipcRenderer: Electron.IpcRenderer;
nativeImage: Electron.nativeImage;
defineCreateMenu: (remote: any) => any[];
getGlobal: (key: string) => any;
getCurrentWindow: () => Electron.BrowserWindow;
updateOpts: (options?: any[]) => void;
createSmartWindow: (options: WinOpts) => void;
triggerNotification: (options?: any) => void;
transferChannel: (channel: string, fnCall: (data: any) => void) => void;
}
declare interface Window {
version: string;
electron: ElectronAPI;
}
// .eslintrc.js
{
globals: {
electron: 'readonly',
},
}
5.Usage - @electron/remote
// src/background.ts
require("@electron/remote/main").initialize();
const win = new BrowserWindow({
width: 1024,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
contextIsolation: true,
nodeIntegration: true,
enableRemoteModule: true,
preload: path.join(__dirname, 'preload.js') // 给窗口注入预加载逻辑
}
})
require("@electron/remote/main").enable(win.webContents);
6.通过import
引入第三方组件库,编写全局声明文件
// shims-usage.d.ts
declare namespace fetchSetting {
interface fetchOptions {
method?: 'GET' | 'POST';
credentials?: string;
MeshPublicInterface?: import('troisjs').MeshPublicInterface
[params: string]: any;
}
type defineUpdate = (state: any) => void;
function fnCall(str: string): void;
type MeshPublicInterface = import('troisjs').MeshPublicInterface
}
type MeshPublicInterface = import('troisjs').MeshPublicInterface
// usage-import.ts
/* eslint-disable @typescript-eslint/no-unused-vars */
const options: fetchSetting.fetchOptions = {
method: 'GET',
credentials: 'include'
}
const fn: fetchSetting.defineUpdate = () => {
console.log('xxxx')
}
let mesh: MeshPublicInterface
let log: typeof Electron.NodeEventEmitter