Electron Vue3 开发笔记(三)

今天开始配置一个完整的项目,如何搭建一个登录页面。登录页面采用ui部分为自定义,没有采用element-plus。该项目背景透明、CSS圆角、标题栏和菜单全部隐藏,采用自定义“关闭”和“最小化”按钮(主进程与渲染进程之间通信)、自定义桌面图标、r任务栏图标等。

Electron分为主进程和渲染进程:

主进程:每个 Electron 应用程序都有一个主进程,作为应用程序的入口点。主进程在 Node.js 环境中运行,这意味着它能够require模块化和使用所有 Node.js API。主要目的是使用 BrowserWindow模块创建和管理应用程序窗口。

渲染进程:由于 Electron 使用 Chromium 来展示页面。每个 Electron 的页面都在运行着自己的进程,这样的进程我们称之为渲染进程。也可以理解为每创建一个 web 页面都会创建一个渲染进程,每个 web 页面都运行在它自己的渲染进程中,每个渲染进程是独立的,它只关心它所运行的页面。

Electron Vue3 开发笔记(三)_第1张图片

 

一、基于vite初始化vue3+typescript项目

yarn create vite electron-project --template vue-ts

二、安装element-plus

yarn add element-plus

三、安装 concurrently cross-env electron-builder wait-on

 yarn add --dev concurrently  cross-env electron-builder wait-on

四、配置调试脚本

  "scripts": {
    "electron:serve": "concurrently -k \"yarn dev\" \"yarn electron\"",
    "electron:build": "vite build && electron-builder",
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview",
    "electron": "wait-on tcp:4000 && cross-env NODE_ENV=development electron ."
  },

五、登录页面-login.html

(1)、html

(2)、typescript



(3)、css


六、路由-router.js

import {createRouter, createWebHashHistory} from 'vue-router';
import login from "../view/login.vue"
const routes = [
    {
        path: '/',
        redirect: '/login'
    },
    {
        path: '/login',
        name: 'login',
        component: login
    }
  
]
const router = createRouter({
    history: createWebHashHistory(),
    routes
})
const ipc = require('electron').ipcRenderer
router.beforeEach((to, from, next) => {
    if (to.path === '/login') return next()
    const token = localStorage.getItem('access-token')
    if (!token) {
        ipc.send("relaunch");
    }
    next()
  })
export default router;

七、入口-main.js

const { app, BrowserWindow, dialog, globalShortcut } = require('electron')
const electron = require('electron');
const path = require('path')
const ipc = require('electron').ipcMain;
const Menu = electron.Menu;
const Tray = electron.Tray;
var appTray = null;
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
ipc.on('new-window', function () {
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, '../dist/main.html'),
    protocol: 'file:',
    slashes: true
  }))
})
const NODE_ENV = process.env.NODE_ENV;
const clearObj = {
  storages: ['appcache', 'filesystem', 'localstorage', 'shadercache', 'websql', 'serviceworkers', 'cachestorage']
};
async function createWindow() {
  const mainWindow = new BrowserWindow({
    frame: false,
    hasShadow: false,
    transparent: true,
    backgroundColor: '#00000000',
    width: 960,
    height: 640,
    useContentSize: true,
    resizable: false,
    show: false,
    icon: 'src/assets/icon/fav256.ico',
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      enableRemoteModule: true,
      nodeIntegration: true,
      webSecurity: false,
      contextIsolation: false
    }
  })
  mainWindow.setAppDetails({
    appId: "com.successkaoyan",
    appIconPath: "./src/assets/icon/fav256.ico",
    appIconIndex: 0,
    relaunchCommand: "Meeting Room",
    relaunchDisplayName: "Meeting Room",
  })
  ipc.on('login', () => {
    mainWindow.setSize(1260, 750);
    mainWindow.center();
  })
  const gotTheLock = app.requestSingleInstanceLock()
  if (!gotTheLock) {
    app.quit()
  } else {
    app.on('second-instance', (event, commandLine, workingDirectory) => {
      if (mainWindow) {
        if (mainWindow.isMinimized()) mainWindow.restore()
        mainWindow.focus()
        mainWindow.show()
      }
    })
  }
  ipc.on('min', e => mainWindow.minimize());
  ipc.on('max', e => {
    if (mainWindow.isMaximized()) {
      mainWindow.unmaximize()
    } else {
      mainWindow.maximize()
    }
  });
  ipc.on('close', e => mainWindow.hide());
  ipc.on('activate', e => {
    mainWindow.setFullScreen(true);
    mainWindow.maximize()
  });
  ipc.on('relaunch', e => {
    app.relaunch(); app.exit();
  })
  var trayMenuTemplate = [

    {
      label: '退出',
      click: function () {
        mainWindow.webContents.session.clearStorageData(clearObj);
        app.quit();
      }
    }
  ];

  mainWindow.on("close",()=>{
    mainWindow.webContents.session.clearStorageData(clearObj);

  })

  if (NODE_ENV === "development") {
    trayIcon = path.join(app.getAppPath(), 'src/assets/icon/fav32.ico');
    mainWindow.webContents.openDevTools()
  } else {
    trayIcon = path.join(__dirname, 'fav32.ico');
  }
  appTray = new Tray(trayIcon);
  const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
  appTray.setToolTip('Meeting Room');
  appTray.setContextMenu(contextMenu);
  appTray.on('click', function () {
    mainWindow.show();
  })
  mainWindow.setMenu(null);
  await mainWindow.loadURL(
    NODE_ENV === "development" ?
      "http://localhost:3000" :
      `file://${path.join(__dirname, "../dist/index.html")}`
  )
  mainWindow.show()
  globalShortcut.register('CommandOrControl+Shift+i', function () {
    mainWindow.webContents.openDevTools()
  })
  globalShortcut.register('CommandOrControl+T', () => {
    mainWindow.maximize()
  })
  globalShortcut.register('CommandOrControl+M', () => {
    mainWindow.unmaximize()
  })
  globalShortcut.register('CommandOrControl+H', () => {
    mainWindow.close()
  })
}
app.whenReady().then(() => {
  createWindow()

})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
  app.quit()
}
app.disableHardwareAcceleration()

七、预加载-preload.js

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])
    }

});

八、项目结构

Electron Vue3 开发笔记(三)_第2张图片

 

你可能感兴趣的:(Electron,electron,vue,typescript,node.js)