Skip to content

electron 实践 - 内嵌 webview

  • new BrowserWindow 配置开启
ts
import { app, BrowserWindow } from 'electron'
import { electronApp, optimizer } from '@electron-toolkit/utils'
import { ipcMainHandle } from './ipc/handle/index'
import { ipcMainOn } from './ipc/on/index'
import { registerShortcuts, unregisterShortcuts } from './shortcut'
import { registerMainIpc, unregisterMainIpc } from './ipc'
import { createWindow } from '@electron/utils/window'
import { copyFileStream } from '@electron/utils/file'
import { getResourcePath, getUserDataPath } from '@electron/utils/path'

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(async () => {
  // Set app user model id for windows
  electronApp.setAppUserModelId('com.electron')

  // Default open or close DevTools by F12 in development
  // and ignore CommandOrControl + R in production.
  // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })
  // 创建浏览器窗口
  createWindow()
  // ipcMain.on:模块注册(更通用方案)
  registerMainIpc()
  // ipcMain.on:直接绑定
  ipcMainOn()
  // ipcMain.handle:直接绑定
  ipcMainHandle()
  //
  registerShortcuts()
  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
  await copyFileStream(getResourcePath('raw/shell/update.exe'), getUserDataPath())
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.once('will-quit', async () => {
  unregisterMainIpc()
  unregisterShortcuts()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
  • vite 配置:webiew 非自定义元素
ts
vue({
  template: {
    compilerOptions: {
      // add electron specific tags
      isCustomElement: (tag) => ['webview'].includes(tag)
    }
  }
})
  • vue组件中 <webview>元素配置,src 配置外部链接,preload 同时注入 <<< @/submodule/play-electron/src/renderer/src/views/webview/index.vue#webviewRef

  • 外部链接中 http://.../files/index.html 调用electron主进程

js
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        background-color: #2b947a;
      }
      ul {
        list-style: none;
      }
      li{
        line-height: 20px;
      }
      h4 {
        padding: 0;
        margin: 0;
      }
    </style>
  </head>
  <body>
    <h4>webview 内嵌内容</h4>
    <ul>
      <li>
        <span>localStorage:</span>
        <span id="localStorage"></span>
        <button id="getItem" >localStorage get</button>
        <button id="setItem">localStorage set</button>
      </li>
      <li>
        <span>isInElectron:</span>
        <span id="isInElectron"></span>
      </li>
      <li>
        <span>调用 preload 中的 ping:</span>
        <button id="ping">ping</button>
      </li>
    </ul>
    <script>
      // 缓存
      const getLocalStorage = () => {
        const test = document.getElementById('localStorage')
        test.innerHTML = `${localStorage.getItem('test')}`
      }
      getLocalStorage()
      const getItem = document.getElementById('getItem')
      getItem.addEventListener('click', () => {
        getLocalStorage()
      })
      const setItem = document.getElementById('setItem')
      setItem.addEventListener('click', () => {
        localStorage.setItem('test', '123')
        getLocalStorage()
      })
    </script>
    <script>
      const isInElectron = document.getElementById('isInElectron')
      isInElectron.innerHTML = window.IS_IN_ELECTRON ? '是(在electron中)' : '否(没有在electron中)'
    </script>
    <script>
      const ping = document.getElementById('ping')
      ping.addEventListener('click', () => {
        window.electron.ipcRenderer.send('ping')
      })
    </script>
  </body>
</html>