国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

Electron 使用預加載腳本

2023-02-16 17:14 更新

學習目標?

在這部分的教程中,你將會了解什么是預加載腳本,并且學會如何使用預加載腳本來安全地將特權 API 暴露至渲染進程中。 不僅如此,你還會學到如何使用 Electron 的進程間通信 (IPC) 模組來讓主進程與渲染進程間進行通信。

什么是預加載腳本?

Electron 的主進程是一個擁有著完全操作系統(tǒng)訪問權限的 Node.js 環(huán)境。 除了 Electron 模組 之外,你也可以使用 Node.js 內置模塊 和所有通過 npm 安裝的軟件包。 另一方面,出于安全原因,渲染進程默認跑在網(wǎng)頁頁面上,而并非 Node.js里。

為了將 Electron 的不同類型的進程橋接在一起,我們需要使用被稱為 預加載 的特殊腳本。

使用預加載腳本來增強渲染器

BrowserWindow 的預加載腳本運行在具有 HTML DOM 和 Node.js、Electron API 的有限子集訪問權限的環(huán)境中。

::: info 預加載腳本沙盒化

從 Electron 20 開始,預加載腳本默認 沙盒化 ,不再擁有完整 Node.js 環(huán)境的訪問權。 實際上,這意味著你只擁有一個 polyfilled 的 require 函數(shù),這個函數(shù)只能訪問一組有限的 API。

可用的 API 詳細信息
Electron 模塊 渲染進程模塊
Node.js 模塊 events、timers、url
Polyfilled 的全局模塊 Bufferprocess、clearImmediatesetImmediate

有關詳細信息,請閱讀 進程沙盒化 教程。

:::

預加載腳本像 Chrome 擴展的 內容腳本(Content Script)一樣,會在渲染器的網(wǎng)頁加載之前注入。 如果你想向渲染器加入需要特殊權限的功能,你可以通過 contextBridge 接口定義 全局對象。

為了演示這一概念,你將會創(chuàng)建一個將應用中的 Chrome、Node、Electron 版本號暴露至渲染器的預加載腳本

新建一個 preload.js 文件。該腳本通過 versions 這一全局變量,將 Electron 的 process.versions 對象暴露給渲染器。

const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
  // 能暴露的不僅僅是函數(shù),我們還可以暴露變量
})

為了將腳本附在渲染進程上,在 BrowserWindow 構造器中使用 webPreferences.preload 傳入腳本的路徑。

const { app, BrowserWindow } = require('electron')
const path = require('path')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})

INFO

這里使用了兩個Node.js概念:

  • __dirname 字符串指向當前正在執(zhí)行腳本的路徑 (在本例中,它指向你的項目的根文件夾)。
  • path.join API 將多個路徑聯(lián)結在一起,創(chuàng)建一個跨平臺的路徑字符串。

現(xiàn)在渲染器能夠全局訪問 versions 了,讓我們快快將里邊的信息顯示在窗口中。 這個變量不僅可以通過 window.versions 訪問,也可以很簡單地使用 versions 來訪問。 新建一個 renderer.js 腳本, 這個腳本使用 document.getElementById DOM 接口來替換 id 屬性為 info 的 HTML 元素顯示文本。

const information = document.getElementById('info')
information.innerText = `本應用正在使用 Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), 和 Electron (v${versions.electron()})`

然后請修改你的 index.html 文件。加上一個 id 屬性為 info 的全新元素,并且記得加上你的 renderer.js 腳本:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>來自 Electron 渲染器的問好!</title>
  </head>
  <body>
    <h1>來自 Electron 渲染器的問好!</h1>
    <p></p>
    <p id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>

做完這幾步之后,你的應用應該長這樣:


你的代碼應該長這樣:

 main.js preload.js  index.html  renderer.js 
const { app, BrowserWindow } = require('electron');
const path = require('path');

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  win.loadFile('index.html');
};

app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
const { contextBridge } = require('electron');

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
});
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello from Electron renderer!</title>
  </head>
  <body>
    <h1>Hello from Electron renderer!</h1>
    <p></p>
    <p id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>
const information = document.getElementById('info');
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;

DOCS/FIDDLES/TUTORIAL-PRELOAD (22.0.2)

Open in Fiddle

在進程之間通信

我們之前提到,Electron 的主進程和渲染進程有著清楚的分工并且不可互換。 這代表著無論是從渲染進程直接訪問 Node.js 接口,亦或者是從主進程訪問 HTML 文檔對象模型 (DOM),都是不可能的。

解決這一問題的方法是使用進程間通信 (IPC)??梢允褂?Electron 的 ipcMain 模塊和 ipcRenderer 模塊來進行進程間通信。 為了從你的網(wǎng)頁向主進程發(fā)送消息,你可以使用 ipcMain.handle 設置一個主進程處理程序(handler),然后在預處理腳本中暴露一個被稱為 ipcRenderer.invoke 的函數(shù)來觸發(fā)該處理程序(handler)。

我們將向渲染器添加一個叫做 ping() 的全局函數(shù)來演示這一點。這個函數(shù)將返回一個從主進程翻山越嶺而來的字符串。

首先,在預處理腳本中設置 invoke 調用:

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
  ping: () => ipcRenderer.invoke('ping'),
  // 能暴露的不僅僅是函數(shù),我們還可以暴露變量
})

IPC 安全

可以注意到我們使用了一個輔助函數(shù)來包裹 ipcRenderer.invoke('ping') 調用,而并非直接通過 context bridge 暴露 ipcRenderer 模塊。 你永遠都不會想要通過預加載直接暴露整個 ipcRenderer 模塊。 這將使得你的渲染器能夠直接向主進程發(fā)送任意的 IPC 信息,會使得其成為惡意代碼最強有力的攻擊媒介。

然后,在主進程中設置你的 handle 監(jiān)聽器。 我們在 HTML 文件加載之前完成了這些,所以才能保證在你從渲染器發(fā)送 invoke 調用之前處理程序能夠準備就緒。

const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })
  ipcMain.handle('ping', () => 'pong')
  win.loadFile('index.html')
}
app.whenReady().then(createWindow)

將發(fā)送器與接收器設置完成之后,現(xiàn)在你可以將信息通過剛剛定義的 'ping' 通道從渲染器發(fā)送至主進程當中。

const func = async () => {
  const response = await window.versions.ping()
  console.log(response) // 打印 'pong'
}

func()

INFO

如欲了解使用 ipcRenderer 模塊和 ipcMain 模塊的詳細說明,請訪問完整的 進程間通信 指南。

摘要

預加載腳本包含在瀏覽器窗口加載網(wǎng)頁之前運行的代碼。 其可訪問 DOM 接口和 Node.js 環(huán)境,并且經(jīng)常在其中使用 contextBridge 接口將特權接口暴露給渲染器。

由于主進程和渲染進程有著完全不同的分工,Electron 應用通常使用預加載腳本來設置進程間通信 (IPC) 接口以在兩種進程之間傳輸任意信息。

在下一部分的教程中,我們將向你展示如何向你的應用中添加更多的功能,之后將向你傳授如何向用戶分發(fā)你的應用。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號