<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      基于electron25+vite4創(chuàng)建多窗口|vue3+electron25新開模態(tài)窗體

      在寫這篇文章的時候,查看了下electron最新穩(wěn)定版本由幾天前24.4.0升級到了25了,不得不說electron團(tuán)隊迭代速度之快!

      前幾天有分享一篇electron24整合vite4全家桶技術(shù)構(gòu)建桌面端vue3應(yīng)用示例程序。

      http://www.rzrgm.cn/xiaoyan2017/p/17436076.html

      這次繼續(xù)接著上次項目,主要介紹electron25結(jié)合vue3技術(shù)實現(xiàn)創(chuàng)建多開窗口及窗口間主/渲染進(jìn)程通信知識。

      隨著electron快速更新,結(jié)合vite的高效構(gòu)建運(yùn)行速度,現(xiàn)在新開一個獨立窗口,打開速度極快。

      electron官網(wǎng)主進(jìn)程模塊BrowserWindow用于創(chuàng)建一個新窗口的方法,提供了非常豐富的API操作用法。

      https://www.electronjs.org/docs/latest/api/browser-window

      // In the main process.
      const { BrowserWindow } = require('electron')
      
      const win = new BrowserWindow({ width: 800, height: 600 })
      
      // Load a remote URL
      win.loadURL('https://github.com')
      
      // Or load a local HTML file
      win.loadFile('index.html')

      如果每次都new一個BrowserWindow窗口,顯得有些笨拙且復(fù)雜。今天要分享的是封裝BrowserWindow方法,只需傳入配置參數(shù),即可快速生成一個獨立窗口。

      createWin({
          title: '關(guān)于About.vue',
          route: '/about',
          width: 600,
          height: 400,
          background: '#fafffa',
          resize: true
      })

      新建一個windows/index.js文件。

      /**
       * 封裝多窗口管理器
       * @author YXY
       */
      
      const { app, BrowserWindow, ipcMain } = require('electron')
      const { join } = require('path')
      
      process.env.ROOT = join(__dirname, '../../')
      
      const isDevelopment = process.env.NODE_ENV == 'development'
      // const winURL = isDevelopment ? 'http://localhost:3000/' : join(__dirname, 'dist/index.html')
      const winURL = isDevelopment ? process.env.VITE_DEV_SERVER_URL : join(process.env.ROOT, 'dist/index.html')
      
      // 配置參數(shù)
      const defaultConfig = {
          id: null,               // 窗口唯一id
          background: '#fff',     // 背景色
          route: '',              // 路由地址url
          title: '',              // 標(biāo)題
          data: null,             // 傳入數(shù)據(jù)參數(shù)
          width: '',              // 窗口寬度
          height: '',             // 窗口高度
          minWidth: '',           // 窗口最小寬度
          minHeight: '',          // 窗口最小高度
          x: '',                  // 窗口相對于屏幕左側(cè)坐標(biāo)
          y: '',                  // 窗口相對于屏幕頂端坐標(biāo)
          resize: true,           // 是否支持縮放
          maximize: false,        // 最大化窗口
          isMultiWin: false,      // 是否支持多開窗口
          isMainWin: false,       // 是否主窗口
          parent: '',             // 父窗口(需傳入父窗口id)
          modal: false,           // 模態(tài)窗口(模態(tài)窗口是浮于父窗口上,禁用父窗口)
          alwaysOnTop: false      // 置頂窗口
      }
      
      class MultiWindows {
          constructor() {
              // 主窗口
              this.mainWin = null
              // 窗口組
              this.winLs = {}
      
              // ...
          }
      
          winOpts() {
              return {
                  // 窗口圖標(biāo)
                  icon: join(process.env.ROOT, 'resource/shortcut.ico'),
                  backgroundColor: '#fff',
                  autoHideMenuBar: true,
                  titleBarStyle: 'hidden',
                  width: 1000,
                  height: 640,
                  resizable: true,
                  minimizable: true,
                  maximizable: true,
                  frame: false,
                  show: false,
                  webPreferences: {
                      contextIsolation: true, // 啟用上下文隔離(為了安全性)(默認(rèn)true)
                      // nodeIntegration: false, // 啟用Node集成(默認(rèn)false)
                      preload: join(process.env.ROOT, 'resource/preload.js'),
                      // devTools: true,
                      // webSecurity: false
                  }
              }
          }
      
          // 創(chuàng)建新窗口
          createWin(options) {
              const args = Object.assign({}, defaultConfig, options)
              console.log(args)
      
              // 判斷窗口是否存在
              for(let i in this.winLs) {
                  if(this.getWin(i) && this.winLs[i].route === args.route && !this.winLs[i].isMultiWin) {
                      this.getWin(i).focus()
                      return
                  }
              }
      
              let opt = this.winOpts()
              if(args.parent) {
                  opt.parent = this.getWin(args.parent)
              }
      
              if(typeof args.modal === 'boolean') opt.modal = args.modal
              if(typeof args.resize === 'boolean') opt.resizable = args.resize
              if(typeof args.alwaysOnTop === 'boolean') opt.alwaysOnTop = args.alwaysOnTop
              if(args.background) opt.backgroundColor = args.background
              if(args.width) opt.width = args.width
              if(args.height) opt.height = args.height
              if(args.minWidth) opt.minWidth = args.minWidth
              if(args.minHeight) opt.minHeight = args.minHeight
              if(args.x) opt.x = args.x
              if(args.y) opt.y = args.y
      
              console.log(opt)
      
              // 創(chuàng)建窗口對象
              let win = new BrowserWindow(opt)
              // 是否最大化
              if(args.maximize && args.resize) {
                  win.maximize()
              }
              this.winLs[win.id] = {
                  route: args.route, isMultiWin: args.isMultiWin
              }
              args.id = win.id
      
      
              // 加載頁面
              let $url
              if(!args.route) {
                  if(process.env.VITE_DEV_SERVER_URL) {
                      // 打開開發(fā)者調(diào)試工具
                      // win.webContents.openDevTools()
          
                      $url = process.env.VITE_DEV_SERVER_URL
                  }else {
                      $url = winURL
                  }
              }else {
                  $url = `${winURL}#${args.route}`
              }
              win.loadURL($url)
              /*if(process.env.VITE_DEV_SERVER_URL) {
                  win.loadURL($url)
              }else {
                  win.loadFile($url)
              }*/
              win.webContents.openDevTools()
      
              win.once('ready-to-show', () => {
                  win.show()
              })
      
              win.on('close', () => win.setOpacity(0))
      
              // 初始化渲染進(jìn)程
              win.webContents.on('did-finish-load', () => {
                  // win.webContents.send('win-loaded', '加載完成~!')
                  win.webContents.send('win-loaded', args)
              })
          }
      
          // 獲取窗口
          getWin(id) {
              return BrowserWindow.fromId(Number(id))
          }
      
          // 獲取全部窗口
          getAllWin() {
              return BrowserWindow.getAllWindows()
          }
      
          // 關(guān)閉全部窗口
          closeAllWin() {
              try {
                  for(let i in this.winLs) {
                      if(this.getWin(i)) {
                          this.getWin(i).close()
                      }else {
                          app.quit()
                      }
                  }
              } catch (error) {
                  console.log(error)
              }
          }
      
          // 開啟主進(jìn)程監(jiān)聽
          ipcMainListen() {
              // 設(shè)置標(biāo)題
              ipcMain.on('set-title', (e, data) => {
                  const webContents = e.sender
                  const wins = BrowserWindow.fromWebContents(webContents)
                  wins.setTitle(data)
      
                  // const wins = BrowserWindow.getFocusedWindow()
                  // wins.setTitle('啦啦啦')
              })
              // 是否最大化(方法一)
              /*ipcMain.on('isMaximized', e => {
                  const win = BrowserWindow.getFocusedWindow()
                  e.sender.send('mainReplay', win.isMaximized())
              })*/
              // 是否最大化(方法二)
              ipcMain.handle('isMaximized', (e) => {
                  const win = BrowserWindow.getFocusedWindow()
                  return win.isMaximized()
              })
      
              ipcMain.on('min', e => {
                  const win = BrowserWindow.getFocusedWindow()
                  win.minimize()
              })
              ipcMain.handle('max2min', e => {
                  const win = BrowserWindow.getFocusedWindow()
                  if(win.isMaximized()) {
                      win.unmaximize()
                      return false
                  }else {
                      win.maximize()
                      return true
                  }
              })
              ipcMain.on('close', (e, data) => {
                  // const wins = BrowserWindow.getFocusedWindow()
                  // wins.close()
                  this.closeAllWin()
              })
      
              // ...
          }
      }
      
      module.exports = MultiWindows

      在主進(jìn)程入口background.js文件引入封裝窗口。

      const { app, BrowserWindow, ipcMain } = require('electron')
      const { join } = require('path')
      
      const MultiWindows = require('./src/windows')
      
      // 屏蔽安全警告
      // ectron Security Warning (Insecure Content-Security-Policy)
      process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
      
      const createWindow = () => {
          let window = new MultiWindows()
      
          window.createWin({isMainWin: true})
          window.ipcMainListen()
      }
      
      app.whenReady().then(() => {
          createWindow()
          app.on('activate', () => {
              if (BrowserWindow.getAllWindows().length === 0) createWindow()
          })
      })
      
      app.on('window-all-closed', () => {
          if (process.platform !== 'darwin') app.quit()
      })

      在主進(jìn)程中做一個ipcMain監(jiān)聽,用來創(chuàng)建獨立窗口。

      ipcMain.on('win-create', (event, args) => this.createWin(args))

      新建windows/action.js文件,處理渲染器進(jìn)程到主進(jìn)程的異步通信,可以發(fā)送同步或異步的消息到主進(jìn)程,也可以接收主進(jìn)程發(fā)送的消息。

      /**
       * 創(chuàng)建新窗口
       * @param {object} args | {width: 640, height: 480, route: '/home'}
       */
      export function createWin(args) {
          window.electronAPI.send('win-create', args)
      }
      
      /**
       * 設(shè)置窗口
       * @param {string} type | 'show'/'hide'/'close'/'min'/'max'/'max2min'/'restore'/'reload'
       * @param {number} id
       */
      export function setWin(type, id) {
          window.electronAPI.send('win-' + type, id)
      }
      
      /**
       * 創(chuàng)建登錄窗口
       */
      export function loginWin() {
          createWin({
              isMainWin: true,
              title: '登錄',
              route: '/login',
              width: 550,
              height: 320,
              resize: false,
              alwaysOnTop: true,
          })
      }

      在vue頁面中調(diào)用上面封裝的方法。

      <template>
          <div class="home">
              ...
      
              <Button type="success" @click="openWin">打開Manage窗口(設(shè)置parent)</Button>
              <Button type="success" @click="openWin1">打開Me窗口(設(shè)置resizable/isMultiWin)</Button>
              <Button type="success" @click="openWin2">打開User窗口</Button>
          </div>
      </template>
      
      <script>
      import { winCfg, createWin } from '@/windows/action'
      
      export default {
          name: 'Home',
          setup() {
              const openWin = () => {
                  MessageBox.confirm('提示', '確定打開Manage頁面嗎? 【設(shè)置parent屬性】', {
                      callback: action => {
                          if(action == 'confirm') {
                              createWin({
                                  title: 'Manage.vue',
                                  route: '/manage',
                                  width: 600,
                                  height: 400,
                                  background: '#09f',
                                  parent: winCfg.window.id,
                                  // modal: true
                              })
                          }else if(action == 'cancel') {
                              Message.info('您已取消!')
                          }
                      }
                  })
              }
      
              const openWin1 = () => {
                  // 左上角
                  // let posX = 0
                  // let posY = 0
      
                  // 右下角
                  let posX = window.screen.availWidth - 850
                  let posY = window.screen.availHeight - 600
                  MessageBox.confirm('提示', '確定打開Me頁面嗎?', {
                      callback: action => {
                          if(action == 'confirm') {
                              createWin({
                                  title: 'Me.vue',
                                  route: '/me?name=Andy',
                                  width: 850,
                                  height: 600,
                                  x: posX,
                                  y: posY,
                                  background: 'yellow',
                                  resize: false,
                                  isMultiWin: true,
                                  maximize: true
                              })
                          }else if(action == 'cancel') {
                              Message.info('您已取消!')
                          }
                      }
                  })
              }
      
              const openWin2 = () => {
                  MessageBox.confirm('提示', '確定打開User頁面嗎?', {
                      callback: action => {
                          if(action == 'confirm') {
                              createWin({
                                  title: 'User.vue',
                                  route: '/user',
                                  width: 700,
                                  height: 550,
                                  minWidth: 300,
                                  minHeight: 300,
                                  data: {
                                      name: 'Andy',
                                      age: 20
                                  },
                                  background: 'green',
                                  isMultiWin: true
                              })
                          }else if(action == 'cancel') {
                              Message.info('您已取消!')
                          }
                      }
                  })
              }
      
              // ...
      
              return {
                  openWin,
                  openWin1,
                  openWin2,
      
                  // ...
              }
          }
      }
      </script>

      設(shè)置 frame: false 創(chuàng)建無邊框窗口。

      設(shè)置 -webkit-app-region: drag 來實現(xiàn)自定義拖拽區(qū)域。設(shè)置后的按鈕操作無法響應(yīng)其它事件,只需設(shè)置 -webkit-app-region: no-drag 即可實現(xiàn)響應(yīng)事件。

      electron+vite提供的一些環(huán)境變量。

      process.env.NODE_ENV
      process.env.VITE_DEV_SERVER_URL

      在開發(fā)環(huán)境,加載vite url,生產(chǎn)環(huán)境,則加載vite build出來的html。

      Ok,綜上就是electron25+vite4結(jié)合構(gòu)建跨端應(yīng)用的一些分享,希望對大家有所幫助哈~~

      附上三個最新原創(chuàng)跨平臺客戶端實例項目

      Tauri2.0+Vite5聊天室|vue3+tauri2+element-plus仿微信|tauri聊天應(yīng)用

      Electron32-ViteOS桌面版os系統(tǒng)|vue3+electron+arco客戶端OS管理模板

      Electron31-Vue3Admin管理系統(tǒng)|vite5+electron+pinia桌面端后臺Exe

       

      posted @ 2023-05-30 10:16  xiaoyan2017  閱讀(2075)  評論(0)    收藏  舉報
      友情鏈接: UP主小店B站
      主站蜘蛛池模板: 久久精品国产中文字幕| 国产精品人妻| 最新的国产成人精品2020| 国产精品视频中文字幕| 国产亚洲无线码一区二区| 亚洲丰满老熟女激情av| 德清县| 免费费很色大片欧一二区| 亚洲一本二区偷拍精品| 国产宅男宅女精品A片在线观看| 色综合伊人色综合网站| 久久高清超碰AV热热久久| 一区二区三区av天堂| 日韩欧美猛交xxxxx无码| 九九热精品视频在线免费| 国产性色的免费视频网站| 欧美黑人大战白嫩在线| 久久成人伊人欧洲精品| 亚洲中文一区二区av| 久久国产精品不只是精品| 亚洲男女羞羞无遮挡久久丫| 久久香蕉国产线看观看怡红院妓院 | 久久婷婷综合色丁香五月| 男人扒女人添高潮视频| 欧美成人h精品网站| 欧美丝袜高跟鞋一区二区| 成人免费无码不卡毛片| 精品久久久久久无码中文野结衣| 日本免费一区二区三区久久| 欧美野外伦姧在线观看| 亚洲人成网站77777在线观看| 亚洲狼人久久伊人久久伊| 久久久久人妻精品一区三寸| 美日韩av一区二区三区| 高平市| 亚洲av午夜福利大精品| 亚洲婷婷综合色高清在线 | 人妻少妇精品无码专区二区| 久久天天躁夜夜躁狠狠综合| 国产精品毛片一区二区| 无码国产精品一区二区av|