vue内嵌网页可以使用iframe实现内嵌网页,但是只能通过postMessage间接通信,在electron环境下,vue可以直接使用webview来内嵌网页,支持 executeJavaScript、postMessage、send 等丰富的通信机制。
使用 webview的优势
性能更佳:独立进程,适合加载复杂网页或 Web App。
更强的 API 控制:支持 executeJavaScript、postMessage、send 等丰富的通信机制。
更强的安全性:启用 contextIsolation、sandbox 等参数可大幅降低攻击面。
使用 iframe的优势
轻量快捷:无需额外配置,简单加载外部网页或静态内容。
兼容性更好:更接近标准 Web 技术,适用于更广泛的项目场景。
注:官方更推荐WebContentsView,webview已经不推荐,但还是能够使用
前端代码 (Vue 3 组件)
<template><div class="content-layout" > <webview ref="webviewRef" :src="url" style="width: 100%; height: 100%;"@dom-ready="onDomReady"></webview></div>
</template><script lang="ts" setup >import { ref, onMounted } from 'vue';const url = ref('https://www.baidu.com');const webviewRef = ref<Electron.WebviewTag | null>(null);onMounted(() => {if (webviewRef.value) {webviewRef.value.addEventListener('dom-ready', () => {webviewRef.value!.executeJavaScript(`console.log("Injected JavaScript: Hello from Electron!");document.body.style.backgroundColor = 'lightblue';`);});}});function onDomReady () {console.log('Webview DOM Ready!');};</script><style scoped>.content-layout {width: 100%;background-color: var(--color-background-content);}
</style>
主进程 (main.js)
在 Electron 主进程中,需要配置 webview 的权限。
const { app, BrowserWindow } = require('electron');let mainWindow;app.whenReady().then(() => {mainWindow = new BrowserWindow({width: 1000,height: 800,webPreferences: {preload: `${__dirname}/preload.js`, // 为 webview 提供安全预加载脚本webviewTag: true, // 启用 webview 标签contextIsolation: true, // 提高安全性enableRemoteModule: false // 禁止远程模块,减少安全风险}});// HMR for renderer base on electron-vite cli.// Load the remote URL for development or the local html file for production.if (is.dev && process.env['ELECTRON_RENDERER_URL']) {mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])} else {mainWindow.loadFile(join(__dirname, '../renderer/index.html'))}});
预加载脚本 (preload.js)
预加载脚本用于在 webview 和 主进程 之间安全地通信
const { contextBridge, ipcRenderer } = require('electron');// 暴露安全 API 给 Webview
contextBridge.exposeInMainWorld('electronAPI', {sendMessage: (message) => ipcRenderer.send('message', message)
});// 监听来自主进程的消息
ipcRenderer.on('reply', (event, response) => {console.log('Received from main process:', response);
});