vue3+ts+vite+electron+electron-store+electron-builder打包可安装包

yarn create vite

yarn add electron
yarn add electron-store
yarn add electron-builder

新增main.js、preload.js

javascript 复制代码
// main.js
const { app, BrowserWindow, ipcMain, globalShortcut } = require('electron')
const path = require('path')
let store // 我们将在稍后动态导入 electron-store

let mainWindow = null

const createWindow = () => {
	mainWindow = new BrowserWindow({
		width: 1200, // 打开界面宽
		minWidth: 1200, // 打开界面最小宽
		height: 800, // 打开界面高
		minHeight: 800, // 打开界面最小高
		fullscreen: false, // 是否启动全屏
		resizable: true, // 是否允许调整窗口大小
		autoHideMenuBar: true, // 工具栏隐藏
		alwaysOnTop: true, // 窗口是否总是显示在其他窗口的上方
		icon: path.join(__dirname, './public/favicon.ico'), // 设置窗口图标
		webPreferences: {
			// 与网页相关的偏好设置
			preload: path.join(__dirname, 'preload.js'),
			contextIsolation: true,
			nodeIntegration: false
		}
	})

	if (process.env.VITE_DEV_SERVER_URL) {
		mainWindow.loadURL(process.env.VITE_DEV_SERVER_URL)
	} else {
		mainWindow.loadFile(path.join(__dirname, './dist/index.html'))
	}

	// 注册刷新页面快捷键
	globalShortcut.register('Ctrl+R', () => {
		mainWindow.reload()
	})

	// 注册打开控制台快捷键
	globalShortcut.register('Ctrl+Shift+I', () => {
		mainWindow.webContents.openDevTools()
	})

	mainWindow.on('closed', () => {
		mainWindow = null
		// 注销所有快捷键
		globalShortcut.unregisterAll()
	})
}

app.whenReady().then(async () => {
	const Store = (await import('electron-store')).default
	store = new Store()
	createWindow()

	// 在所有窗口关闭时注销快捷键
	app.on('window-all-closed', () => {
		globalShortcut.unregisterAll()
		if (process.platform !== 'darwin') {
			app.quit()
		}
	})

	app.on('activate', () => {
		if (BrowserWindow.getAllWindows().length === 0) {
			createWindow()
		}
	})
})

ipcMain.handle('getStoreValue', (event, key) => {
	return store.get(key)
})

ipcMain.handle('setStoreValue', (event, key, value) => {
	store.set(key, value)
})
ipcMain.handle('delStoreValue', () => {
	store.clear()
	console.log('已经清理')
})
javascript 复制代码
// preload.js
const { contextBridge, ipcRenderer } = require('electron')

// 向渲染进程暴露 Electron 特定的 API
contextBridge.exposeInMainWorld('electron', {
	getStoreValue: (key) => ipcRenderer.invoke('getStoreValue', key),
	setStoreValue: (key, value) =>
		ipcRenderer.invoke('setStoreValue', key, value),
	delStoreValue: () => ipcRenderer.invoke('delStoreValue')
})

// 添加全局变量来指示是否在 Electron 环境中运行
contextBridge.exposeInMainWorld('isElectron', true)

window.addEventListener('DOMContentLoaded', () => {
	const replaceText = (selector, text) => {
		const element = document.getElementById(selector)
		if (element) element.innerText = text
	}

	for (const dependency of ['chrome', 'node', 'electron']) {
		replaceText(`${dependency}-version`, process.versions[dependency])
	}
})
TypeScript 复制代码
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base: "./",    // 必须
});
TypeScript 复制代码
// app页面添加electron-store测试代码
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
// 用于测试electron-store
setTimeout(() => {
 
 console.log('写入', window.electron)

 window.electron.setStoreValue('key', '我是写入数据')

}, 1000)

setTimeout(() => {

 const v = window.electron.getStoreValue('key')

 console.log('读取', v)

}, 5000)

</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
TypeScript 复制代码
// src/electron.d.ts

export interface ElectronAPI {
  getStoreValue: (key: string) => Promise<any>;

  setStoreValue: (key: string, value: any) => Promise<void>;
}

declare global {
  interface Window {
    electron: ElectronAPI;
  }
}
TypeScript 复制代码
 "name": "test",
  "private": true,
  "version": "0.0.0",  // 新增
  "description": "hello world",// 新增
  "main": "main.js", // 新增
  "author": "han",  // 新增
  "license": "MIT",   // 新增
"scripts": {
    "dev": "vite",
    "build": "vue-tsc -b && vite build",
    "start": "electron .",    // 新增
    "build-builder": "electron-builder",  // 新增
    "preview": "vite preview"
  },
 "build": {  // 新增build
    "appId": "com.yourcompany.yourapp",
    "win": {
      "target": "nsis",
      "icon": "./public/icon.ico"
    },
    "linux": {
      "icon": "./public/icon.png"
    },
    "dmg": {
      "contents": [
        {
          "x": 410,
          "y": 150,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 150,
          "type": "file"
        }
      ]
    },
    "mac": {
      "icon": "./public/icon.ico"
    },
    "files": [
      "dist/**/*",
      "main.js",
      "preload.js"
    ],
    "directories": {
      "output": "awBack2"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "aw"
    }
  },

yarn build
yarn start

yarn build-builder

TypeScript 复制代码
{
  "name": "test",
  "private": true,
  "version": "0.0.0",
  "description": "hello world",
  "main": "main.js",
  "author": "han",
  "license": "MIT",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc -b && vite build",
    "start": "electron .",
    "build-builder": "electron-builder",
    "preview": "vite preview"
  },
  "build": {
    "appId": "com.yourcompany.yourapp",
    "win": {
      "target": "nsis",
      "icon": "./public/icon.ico"
    },
    "linux": {
      "icon": "./public/icon.png"
    },
    "dmg": {
      "contents": [
        {
          "x": 410,
          "y": 150,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 150,
          "type": "file"
        }
      ]
    },
    "mac": {
      "icon": "./public/icon.ico"
    },
    "files": [
      "dist/**/*",
      "main.js",
      "preload.js"
    ],
    "directories": {
      "output": "awBack2"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "aw"
    }
  },
  "dependencies": {
    "electron-store": "^10.0.0",
    "vue": "^3.4.37"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.1.2",
    "electron": "^32.0.1",
    "electron-builder": "^24.13.3",
    "typescript": "^5.5.3",
    "vite": "^5.4.1",
    "vue-tsc": "^2.0.29"
  }
}

相关推荐
开心工作室_kaic1 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā1 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年2 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727572 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart3 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
会发光的猪。3 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客3 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记3 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安4 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js