国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Electron 如何調用本地模塊的方法

2019-11-19 12:10:54
字體:
來源:轉載
供稿:網友

Electron 結合了 Chromium、Node.js 和用于調用操作系統本地功能的 API(如打開文件窗口、通知、圖標等,基于 Electron 的開發,就好像開發一個網頁一樣,而且能夠無縫地使用 Node。或者說:就好像構建一個 Node app,并通過 HTML 和 CSS 構建界面。

那么如何在頁面中調用 Node API 呢?

碰到了一些坑…

先從頁面加載方式說起,Electron 中加載頁面的方式有兩種:
一種是直接加載本地文件,另一種是通過 http 網絡請求頁面。

//方法1 本地路徑win.loadURL(url.format({  pathname: path.join(__dirname, '/dist/index.html'),  protocol: 'file:',  slashes: true}));
//方法2 網絡路徑win.loadURL('http://localhost:3000');

現在我想要在某個js文件中引用一個本地的 npm 包,其中包含 Node API,所以在瀏覽器中無法使用。

var local = window.nodeRequire('local');

此時出現一個問題,使用方法1運行正常,但使用方法2時報錯,但是如果使用方法1,每次修改完代碼都需要先打包一遍,再使用 Electron 啟動,耗時耗力啊。繼續尋找解決方法。

can not find module xxx

調試發現在使用網絡文件時,在調用 module.js 中的 Module._load 函數時參入的參數 parent 為

重點在下面兩個變量,從 Http 加載頁面時,由于路徑是網絡地址,所以 Electron 將文件名設置為 Electron 安裝目錄下的 init.js.

filename: "C:/Users/asus/AppData/Roaming/npm/node_modules/electron/dist/resources/electron.asar/renderer/init.js"
paths: Array[0]

而在使用本地 index.html 時,pathname 指向正確的路徑,而且 paths 中也包含了多個 node_modules 路徑,module在初始化時會將當前路徑以及上一級、上上一級…直到根目錄的 node_modules 作為搜索路徑。

filename: "E:/WebStormWorkspace/electron_require/index.html"

從下面 module.js 源碼可以看到,文件名解析的時候正式利用了這個 paths 中的路徑。因為 paths 中的空的,所以找不到所需要的模塊。

其實 Electron 是從安全的角度考慮,在從 Http 請求中加載網頁時,如果能直接調用本地的一些模塊,會比較危險。

Module._resolveFilename = function(request, parent, isMain) { if (NativeModule.nonInternalExists(request)) {  return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; // look up the filename first, since that's the cache key. debug('looking for %j in %j', id, paths); var filename = Module._findPath(request, paths, isMain); if (!filename) {  var err = new Error("Cannot find module '" + request + "'");  err.code = 'MODULE_NOT_FOUND';  throw err; } return filename;};

此時很自然地想到可以把所需要模塊的路徑加入到 paths 中去,但這其實是不可行的,Electron 包含主進程和渲染進程,主進程就是這里命名main.js 的文件,該文件是每個 Electron 應用的入口。它控制了應用的生命周期(從打開到關閉)。它能調用原生元素和創建新的(多個)渲染進程,而且整個 Node API 是內置其中的。

渲染進程就是一個瀏覽器窗口,現在我們的 js 跑在渲染進程里面,所以我們并不能直接在主進程里面修改渲染進程的數據。

Electron 提供了 IPC 接口專門用于主進程和渲染進程之間的通信,他提供了同步和異步兩種方法,同步方法直接設置 event.returnValue,異步方法使用 event.sender.send(…).

// In main process.const {ipcMain} = require('electron')ipcMain.on('asynchronous-message', (event, arg) => { console.log(arg) // prints "ping" event.sender.send('asynchronous-reply', 'pong')})ipcMain.on('synchronous-message', (event, arg) => { console.log(arg) // prints "ping" event.returnValue = 'pong'})
// In renderer process (web page).const {ipcRenderer} = require('electron')console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"ipcRenderer.on('asynchronous-reply', (event, arg) => { console.log(arg) // prints "pong"})ipcRenderer.send('asynchronous-message', 'ping')

但其實有更簡單的方法,使用 remote 模塊來直接調用:

const remote = window.nodeRequire('electron').remote;var local = remote.require('local');

這樣子就可以直接使用外部模塊了,這里為什么能引用 electron 模塊,而其他的不可以呢?

繼續看源碼, Electron 重寫了 Module._resolveFilename 函數,在 require(‘electron') 時,就直接返回路徑,所以就可以找到啦。

// Patch Module._resolveFilename to always require the Electron API when// require('electron') is done.const electronPath = path.join(__dirname, '..', process.type, 'api', 'exports', 'electron.js')const originalResolveFilename = Module._resolveFilenameModule._resolveFilename = function (request, parent, isMain) { if (request === 'electron') {  return electronPath } else {  return originalResolveFilename(request, parent, isMain) }}}.call(this, exports, require, module, __filename, __dirname); });

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临安市| 东乌珠穆沁旗| 衢州市| 土默特左旗| 桐城市| 江城| 靖远县| 和平区| 佛冈县| 马鞍山市| 上蔡县| 洪雅县| 绵竹市| 汤阴县| 会昌县| 大名县| 临武县| 安庆市| 鹤岗市| 中宁县| 南江县| 资阳市| 东乡县| 布尔津县| 湖北省| 黄陵县| 澎湖县| 岫岩| 洱源县| 龙口市| 枝江市| 泉州市| 呼和浩特市| 桦川县| 广西| 宝坻区| 万山特区| 界首市| 喀什市| 民权县| 兴业县|