一、Webview
Electron 中 webview 是 electron 框架自带的组件,用于加载 web 应用。与 web 通信的原理如下:
webview => web
// webview 发送webview.send('channel_name_in_react_component', args);// web 监听ipcRenderer.on('channelNamel', (event, args) {// do whatever});
web => webview ``` // web 发送 import {ipcRenderer} from ‘electron’ ipcRenderer.sendToHost(‘channelName’, …args)
// webview 监听 webview.addEventListener(‘ipc-message’, onIpcMessage)
function onIpcMessage(event) { const {args, channel} = event console.log(channel, args) }
这些逻辑一般封装在一个 bridge.js 里,然后让 webview 预加载这个文件```javascript// bridge.jsconst { ipcRenderer } = require("electron");const SupportedMethods = ["send"];class WebViewBridge {constructor() {window.WebView = window.CommonWebView = this.getWebView();this.listen();}getWebView() {const WebView = {};SupportedMethods.forEach((api) => {WebView[api] = (params) => {this._webviewMessageSender(api, params);};});return WebView;}_webviewMessageSender(method, params) {try {params = JSON.parse(params);} catch (e) {console.error(`[WebViewBridge] PARSE BASE64 ERRORparams: ${params}e: ${e}`);return;}ipcRenderer.sendToHost(method, params.arguments[0]);}listen() {ipcRenderer.on("electron-webview-channel", (event, callbackName, data) => {try {console.log("==", event, callbackName, data);window[callbackName](data);} catch (e) {console.error(`[WebViewBridge] CALLBACK ERRORcallbackName: ${callbackName}data: ${data}detail: ${e}`);}});}}new WebViewBridge();
- 使用 webview 时要注意开启两点: ```javascript const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, webviewTag: true, // 1、启用 webview }, });
<!DOCTYPE html>
<a name="hWLIC"></a>## 二、BrowserWindow主进程使用<br />1、用于在主进程创建和控制浏览器窗口,可以创建出无边框窗口(可以自定义header)、透明窗口(用于制作不规则界面)、父子窗口、模态窗口<br />2、往往需要通过 -webkit-app-region 设置可拖拽区域:```html<body style="-webkit-app-region: drag"></body>button {-webkit-app-region: no-drag;}
3、为避免闪烁,展示窗口的时机应该在 ready-to-show 或者 did-finish-load 事件之后
const { BrowserWindow } = require('electron')const win = new BrowserWindow({ show: false })win.once('ready-to-show', () => {win.show() // 如果还是有白屏现象,可以换成 did-finish-load 事件})
4、常用事件
- close、closed 将要关闭和已经关闭
- blur、focus、show、hide、maxmize、unmaxmize、minimize、restore
5、常用静态方法
- getAllWindows
- getFocusedWindow
- fromWebContents
- fromBrowserView
- fromId
6、常用属性和方法
- id
- webContents
- close() 和用户点击关闭按钮效果一样,关闭操作可能被 web 取消
- destroy() 强制关闭窗口,只会触发 closed;不会触发 close、beforeunload、unload
- focus()、blur()、isFocused()、isDestroyed()、isVisible()、isModal()、minimize()、restore()
- show()、hide()
- loadUrl(url,options) url 可以是远程地址 (例如 http://),也可以是 file:// 协议的本地HTML文件的路径. 与 webContents.loadUrl(url,options) 功能相似: ```javascript // 确保 url 符合要求 const url = require(‘url’).format({ protocol: ‘file’, slashes: true, pathname: require(‘path’).join(__dirname, ‘index.html’) })
win.loadURL(url)
- loadFile(file) 与 webContents.loadFile(file) 功能相似:<a name="QJcuk"></a>## 三、webContents主进程使用<br />1、webContents 是 EventEmitter. 负责渲染和控制网页, 是 BrowserWindow 对象的一个属性。```javascriptconst { BrowserWindow } = require('electron')const win = new BrowserWindow({ width: 800, height: 1500 })win.loadURL('http://github.com')const contents = win.webContentsconsole.log(contents)
2、可以通过 electron 直接引入
const { webContents } = require('electron')console.log(webContents)
3、常用静态方法
- getAllWebContents(),包含所有Windows,webviews,opened devtools 和 devtools 扩展背景页的 web 内容
- getFocusedWebContents()
- fromId()
4、常用事件
- dom-ready
- did-finish-load
- render-process-gone
- plugin-crashed
- destroyed
- ipc-message IPC 通信
5、常用实例方法和属性
- downloadURL() 下载文件,开始后会触发对应 session 的 will-download 事件 ```javascript // 触发下载 win.webContents.downloadURL(url)
// 监听 will-download session.defaultSession.on(‘will-download’, (event, item, webContents) => { // 监听 item 的 pause、resume、cancel、updated、done 等事件处理下载逻辑 })
- goBack()- goForward()- canGoBack()- canGoForward()- setUserAgent()- postMessage() 主进程发送事件,渲染进程接受 ipcRender.on- id- session- userAgent<a name="SsBDI"></a>## 四、session主进程使用<br />管理浏览器会话、cookie、缓存、代理设置等。```javascriptconst { BrowserWindow } = require('electron')const win = new BrowserWindow({ width: 800, height: 600 })win.loadURL('http://github.com')const ses = win.webContents.sessionconsole.log(ses.getUserAgent())
1、静态方法和属性
- fromPartition(partition),如果 partition 以 persist:开头, 该页面将使用持续的 session,并在所有页面生效,且使用同一个partition. 如果没有 persist: 前缀, 页面将使用 in-memory session. 如果没有设置partition,app 将返回默认的session。
- defaultSession 应用程序的默认session对象
2、实例属性和方法
- clearStorageData(options),可以清除:appcache, cookies, filesystem, indexdb, localstorage, shadercache, websql, serviceworkers, cachestorage
- setUserAgent()
- loadExtention() 设置扩展程序 ```javascript const { app, session } = require(‘electron’) const path = require(‘path’)
app.on(‘ready’, async () => { await session.loadExtension( path.join(__dirname, ‘react-devtools’), // allowFileAccess is required to load the devtools extension on file:// URLs. { allowFileAccess: true } ) // Note that in order to use the React DevTools extension, you’ll need to // download and unzip a copy of the extension. })
- cookies```javascriptimport { Cookie, CookiesGetFilter, CookiesSetDetails, session } from 'electron';import { fileURLToPath } from 'url';const SessionPartition = 'persist:my-app';/*** PersistentSession* Session 持久化管理*/class PersistentSession {private _session: session | null = null;init() {if (this._session) {return;}this._session = session.fromPartition(SessionPartition, { cache: false });// workaround in https://github.com/electron/electron/issues/23757this._session.protocol.registerFileProtocol('file', (request, callback) => {callback({ path: fileURLToPath(request.url) });});}get session(): session {if (!this._session) {this.init();}return this._session;}get partition(): string {if (!this._session) {this.init();}return SessionPartition;}async getCookies(filter: CookiesGetFilter): Promise<Cookie[]> {try {return await this.session.cookies.get(filter);} catch (error) {return [];}}async setCookies(details: CookiesSetDetails): Promise<void> {try {await this.session.cookies.set(details);} catch (error) {}}async removeCookies(url: string, name: string): Promise<void> {try {await this.session.cookies.remove(url, name);} catch (error) {}}async clearAllCookies(): Promise<void> {try {await this.session.clearStorageData({ storages: ['cookies'] });} catch (error) {}}async flushCookies(): Promise<void> {try {await this.session.cookies.flushStore();} catch (error) {}}}export const persistentSession = new PersistentSession();
- webRequest 可以设置拦截,如加些请求 header
参考:
Electron webview完全指南
BrowserWindow
