electron+vue3全家桶+vite项目搭建【27】封装窗口工具类【1】雏形

文章目录

引入

demo项目地址

可以看到我们之前在主进程中的逻辑全部都塞到index.ts文件中,包括窗口的一些事件处理,handle监听,协议注册等等,后期维护起来会比较麻烦,我们不妨将其中的功能细分,封装到工具类中。

思路

以新建窗口举例,流程为

  • 主进程ipcMain.handle监听,根据传来的参数构建新窗口
ts 复制代码
/**
 * 新建一个窗口
 * route=>路由地址  paramJsonStr => 序列化后的参数对象
 */
ipcMain.handle("open-win", (_, route: string, paramJsonStr: string) => {...})
  • 渲染进程调用 ipcRenderer.invoke方法通知主进程创建窗口
ts 复制代码
/**
 * 新建一个窗口
 * @param path 路由地址
 * @param param 传递的参数
 */
export function openWindow(path: string, param?: Object) {
  ...
  ipcRenderer.invoke("open-win", path, paramJsonStr);
}

可以预见的是,后续窗口的创建逻辑会随着业务逻辑而扩展,例如创建窗口时 指定窗口宽高,标题,背景色等属性,设置窗口透明,事件击穿等等内容,并且多个窗口间的一些交互需要我们去维护一个窗口组信息,记录窗口的id和逻辑上的关联关系等。

所以我们不妨创建一个窗口工具类,专门集成封装窗口相关的方法,属性等

抽出公共声明文件

我们在渲染进程项目模块中的electronUtils和主进程中的窗口工具类中的【handle/on】方法是一一对应的【invoke/send】,传入的参数也是通用的,所以我们不妨抽出一个公共的全局声明文件,用于声明通用的一些参数对象。

1.在全局声明文件中添加通用事件对象的声明

  • types\global.d.ts
typescript 复制代码
/** 一些全局的对象补充声明 */
export {};
declare global {
	...
      // 窗口创建参数规范
  interface IWindowConfig {
    key?: string; // 窗口唯一key,不传则取窗口的id,假如已存在该key则聚焦该窗口
    route?: string; // 窗口路由
    width?: number; // 窗口宽度
    height?: number; // 窗口高度
    param?: string; // 传递参数,新窗口打开时能直接从路由中获取,拼接url传递,推荐只传小数据
  }
}

2.主进程引入全局声明文件

  • electron\electron-env.d.ts
ts 复制代码
/// <reference types="vite-plugin-electron/electron-env" />

import "../types/global.d.ts";

抽出全局通用数据类型和方法

主进程和渲染进程都会调用相同的事件名称,所以我们不妨定义一个全局的事件枚举类,方便两个进程的代码书写和规范【事件名称应当唯一,否则会重复绑定】。

1.在根目录下创建globel目录,然后分别创建channelEvent.ts和channelEvent.d.ts两个文件 【事件管道枚举和对应的声明文件】

  • globel\channelEvent.ts
ts 复制代码
/**
 * 自定义事件枚举
 */
export enum CustomChannel {
  window_create = "custom_window_create", // 窗口新建事件
  window_move_on = "custom_window_move_on", // 开启窗口移动事件
  window_position_change = "custom_window_position_change", // 修改窗口的位置
}
  • globel\channelEvent.d.ts
ts 复制代码
// customEvents.d.ts

/**
 * 自定义事件枚举的类型声明
 */
export declare enum CustomChannel {
  window_create = "custom_window_create", // 窗口新建事件
  window_move_on = "custom_window_move_on", // 开启窗口移动事件
  window_position_change = "custom_window_position_change", // 修改窗口的位置
}

2.在根目录下的tsconfig.node.json文件中添加引入

  • tsconfig.node.json
json 复制代码
  "include": [...,"globel"]

3.配置别名快速访问

  • vite.config.ts
ts 复制代码
... 
resolve: {
      alias: {
		...
        "@globel": path.resolve(__dirname, "./globel"),
      },
    },
  • tsconfig.json
json 复制代码
{
  "compilerOptions": {
	...
    "paths": {
        ...
      "@globel/*": ["globel/*"],
    },
    "types": ["vite-plugin-svg-icons/client"]
  },

}

主进程模块

1.抽离基础常量

我们将主进程中常用的常量抽离到单独的文件中:

  • electron\main\common\variables.ts
ts 复制代码
import { join } from 'node:path';

/**
 *公共变量配置
 */
process.env.DIST_ELECTRON = join(__dirname, '..');
process.env.DIST = join(process.env.DIST_ELECTRON, '../dist');
process.env.PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? join(process.env.DIST_ELECTRON, '../public')
  : process.env.DIST;

// 公共变量中存一份SRC的路径,方便取值
process.env.SRC_PATH = join(__dirname, '../../src').split('\\').join('/');

// 预加载文件路径
export const preloadPath = join(__dirname, '../preload/index.js');
// dev环境请求地址
export const url = process.env.VITE_DEV_SERVER_URL;
// 部署环境的html文件路径
export const indexHtmlPath = join(process.env.DIST, 'index.html');
// icon图标地址
export const iconPath = join(process.env.PUBLIC, 'icons/icon.ico');
// app的title,会被index.html中配置的<title>%VITE_APP_TITLE%</title> 覆盖
export const appTitle = "新窗口";
// app在windows上注册表的协议
export const PROTOCOL = 'bcxlelectrondemo';

2.封装窗口工具类

注意:

1.定义默认窗口参数时使用了ts中的联合类型,这样定义的defaultWindowConfig就必须拥有指定的两个类型中的所有属性

2.创建了一个窗口类,并将窗口相关的逻辑封装为窗口类中的成员方法

3.窗口类中定义个一个listen方法,里面放置所有需要与渲染进程交互的handle监听

  • electron\main\windowUtils.ts
ts 复制代码
import {
  BrowserWindow,
  BrowserWindowConstructorOptions,
  ipcMain,
} from "electron";
import {
  url,
  appTitle,
  preloadPath,
  iconPath,
  indexHtmlPath,
} from "./common/variables";
import { CustomChannel } from "../../globel/channelEvent";

/* ======================= 定义一些窗口工具类中会使用到的常量,以及窗口顶级父类 ========================= */

// 默认窗口参数
export const defaultWindowConfig: BrowserWindowConstructorOptions &
  IWindowConfig = {
  title: appTitle,
  icon: iconPath,
  width: 800,
  height: 600,
  webPreferences: {
    webviewTag: true,
    preload: preloadPath,
    nodeIntegration: true,
    contextIsolation: false,
  },
};

/**
 * 窗口工具类
 */
export class WindowUtils {
  // 事件监听处理
  listen() {
    // 窗口创建监听
    ipcMain.handle(CustomChannel.window_create, (_, opt: IWindowConfig) => {
      this.createWindows(opt);
    });
  }

  /**
   * 创建窗口
   * @param windowConfig 窗口创建参数
   */
  createWindows(windowConfig: IWindowConfig): BrowserWindow {
    // 创建窗口对象
    const win = new BrowserWindow(
      Object.assign({}, defaultWindowConfig, windowConfig)
    );

    // 根据当前环境加载页面,并传递参数
    const param = windowConfig.param
      ? "?urlParamData=" + windowConfig.param
      : "";
    if (process.env.VITE_DEV_SERVER_URL) {
      // 如果是开发环境,则直接访问本地跑起的服务,拼接对应的路由
      win.loadURL(`${url}#${windowConfig.route}${param}`);
    } else {
      // 如果是线上环境,则加载html文件的路径,然后拼接路由
      win.loadFile(indexHtmlPath, { hash: windowConfig.route + param });
    }

    // 绑定通用窗口事件
    return win;
  }
}

接着我们调整index.ts中的创建主窗口的代码:

ts 复制代码
import {WindowUtils} from './windowUtils'


// 创建窗口工具类
const windowUtils = new WindowUtils();
windowUtils.listen();

...
async function createWindow() {
    ...
    win = windowUtils.createWindows({
        route:"/"
      });
}

对比之前代码,简练了不少

渲染进程模块

1.我们调整通用交互工具类,补充新的窗口创建方法

  • src\utils\electronUtils.ts
ts 复制代码
import { ipcRenderer } from "electron";
import { CustomChannel } from "@globel/channelEvent";
/**
 * 新建一个窗口
 * @param windowConfig
 */
export function createWindow(windowConfig: IWindowConfig) {
  ipcRenderer.invoke(CustomChannel.window_create, windowConfig);
}

2.调整demo代码

  • src\components\demo\Index.vue
vue 复制代码
 electronUtils.createWindow({
    route: windowPath.value,
    param: JSON.stringify({
      message: "向你问个好~~",
    }),
  });

测试结果

能够正常的创建窗口

相关推荐
SL-staff1 天前
Vue3私有化AI白板落地实战|解决政企项目智能绘图合规难题(可直接复用源码)
人工智能·低代码·开源·vue3·白板·jvs规则引擎·jvs-draw
雨季mo浅忆1 天前
Cursor快速实现上传Excel功能
前端·vue3·ai编程
ANnianStriver3 天前
PetLumina-AI 驱动的宠物生活管理平台
java·生活·vue3·springboot·ai编程·宠物·全栈开发
雨季mo浅忆4 天前
记录Vue3项目中的各类问题
前端·bug·vue3
八目蛛7 天前
八目蛛网络(免费工具网站导航)
css·vue.js·开源·vue3·html5·ai编程
颂love7 天前
Vue3基础入门
前端·学习·vue3
海市公约8 天前
Vue3组合式API中watch传值生命周期与自定义Hook实战
vue3·生命周期·watch·props·组件通信·defineexpose·自定义hook
海市公约9 天前
Vue3组合式API与响应式系统核心机制详解
vue3·computed·reactive·ref·响应式系统·composition api·script setup
小茴香35310 天前
Vue3路由权限动态管理
前端·前端框架·vue3
暗冰ཏོ14 天前
《2026 Vue2 + Vue3 完整学习指南:基础语法、路由缓存、登录拦截、项目实战与面试题》
前端·vue.js·vue·vue3·vue2