Bagaimana untuk mendapatkan direktori AppData yang dipramuat?
background.js
[...] async function createWindow() { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__static, "preload.js"), nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION }, }) } [...]
pramuat.js
const { contextBridge } = require('electron') contextBridge.exposeInMainWorld( 'configManager', require("../src/utils/config-manager") )
config-manager.js
const app = require("electron").app const fs = require("fs") const resourcePath = app.getPath('appData').replaceAll("\", "/") + "my-custom-path" // <--- const configPath = resourcePath + "config.json" const defaultConfig = [ ... ] let config; function createFilesIfNotExists(){ if (!fs.existsSync(resourcePath)) fs.mkdirSync(resourcePath) if (!fs.existsSync(configPath)){ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4)) return true } return false } module.exports = { loadConfig() { createFilesIfNotExists() [...] return config } }
Jika saya menjalankan ini, saya mendapat ralat ini.
TypeError: Cannot read property 'getPath' of undefined at Object.<anonymous> (VM77 config-manager.js:3) at Object.<anonymous> (VM77 config-manager.js:65) at Module._compile (VM43 loader.js:1078) at Object.Module._extensions..js (VM43 loader.js:1108) at Module.load (VM43 loader.js:935) at Module._load (VM43 loader.js:776) at Function.f._load (VM70 asar_bundle.js:5) at Function.o._load (VM75 renderer_init.js:33) at Module.require (VM43 loader.js:959) at require (VM50 helpers.js:88) (anonymous) @ VM75 renderer_init.js:93
Saya rasa ini berlaku kerana "apl" dimulakan kemudian.
Matlamat utama saya ialah membaca konfigurasi json daripada direktori AppData.
Jika ada cara yang lebih baik untuk melakukan ini, sila beritahu saya.
Pengguna tidak perlu boleh menukar konfigurasi semasa runtime. Tetapi saya harus dapat menulis nilai lalai dalam defaultConfig
ke dalam fail konfigurasi.
app.getPath()
方法僅在應(yīng)用程序“就緒”后才可用。使用 app.on('ready' () => { ... });
Kesan acara 'sedia'. Untuk maklumat lanjut, lihat acara Electron: 'bersedia'.
Mengenai anda preload.js
腳本,直接在其中包含函數(shù)有時(shí)會(huì)使內(nèi)容難以閱讀和理解(即使它僅由 require
實(shí)現(xiàn))。目前,該文件沒(méi)有關(guān)注點(diǎn)分離。 IE:您的“配置”功能混合在 preload
腳本中。如果您希望分離問(wèn)題,那么您應(yīng)該從 preload.js
文件中重構(gòu)您的“配置”代碼,并將其放在自己的文件中。這樣,您的 preload.js
fail hanya digunakan untuk mengkonfigurasi saluran IPC dan memindahkan data yang berkaitan (jika ada).
Baiklah, mari kita lihat bagaimana untuk menyelesaikan masalah app.getPath('appData')
.
Dalam main.js
文件中,檢測(cè)您的應(yīng)用程序何時(shí)“就緒”,然后通過(guò)您的 config-manager.js
文件獲取 appData
direktori anda.
main.js
(benang utama)
const electronApp = require('electron').app; const electronBrowserWindow = require('electron').BrowserWindow; let appConfig = require('config-manager'); let appMainWindow = require('mainWindow'); let mainWindow; app.whenReady().then(() => { // Load the config. let configStatus = appConfig.loadConfig(); console.log(configStatus); let config = appConfig.getConfig(); console.log(config); // Create your main window. mainWindow = appMainWindow.create() ... }) })
di luar skop fungsi config-manager.js
文件中,我已將您的“路徑”變量移至 loadConfig()
函數(shù)范圍,因?yàn)樗鼈儍H由該函數(shù)使用。如果您需要將它們公開以供文件中其他位置使用,則需要將它們移回 loadConfig()
anda.
Saya mengalihkan rujukan kepada ElectronApp.getPath('appData')
ke dalam fungsi loadConfig()
kerana fungsi ini dipanggil daripada ElectronApp.getPath('appData')
的引用移至 loadConfig()
函數(shù)中,因?yàn)樵趹?yīng)用程序“就緒”后從 main.js
selepas aplikasi "sedia".
Saya menambah fungsi pembantu pathExists()
kerana pelaksanaannya digunakan beberapa kali.
Akhirnya, saya menambah getConfig()
函數(shù),以便在需要時(shí)從應(yīng)用程序主線程中的任何位置輕松獲取配置對(duì)象(只要將其包含在需要使用它的文件中即可)。IE: let appConfig = require('config-manager')
.
config-manager.js
(benang utama)
const electronApp = require("electron").app const nodeFs = require("fs") const defaultConfig = [ ... ]; let config; function loadConfig() { let resourcePath = app.getPath('appData').replaceAll("\", "/") + "my-custom-path"; let configPath = resourcePath + "config.json"; if (! pathexists(resourcePath)) { nodeFs.mkdirSync(resourcePath); } if (! pathexists(configPath)) { nodeFs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4)); config = defaultConfig; } else { config = JSON.parse(nodeFs.readFileSync(configPath , 'utf8')); }; } function getConfig() { return config; } function pathExists(path) { return (fs.existsSync(path)) ? true : false; } module.exports = {loadConfig, getConfig}
Skrip preload.js
tipikal kelihatan seperti ini.
const contextBridge = require('electron').contextBridge; const ipcRenderer = require('electron').ipcRenderer; // White-listed channels. const ipc = { 'render': { // From render to main. 'send': [ 'config:updateConfig' // Example only ], // From main to render. 'receive': [ 'config:showConfig' // Exmaple only ], // From render to main and back again. 'sendReceive': [] } }; contextBridge.exposeInMainWorld( // Allowed 'ipcRenderer' methods. 'ipcRender', { // From render to main. send: (channel, args) => { let validChannels = ipc.render.send; if (validChannels.includes(channel)) { ipcRenderer.send(channel, args); } }, // From main to render. receive: (channel, listener) => { let validChannels = ipc.render.receive; if (validChannels.includes(channel)) { // Deliberately strip event as it includes `sender` ipcRenderer.on(channel, (event, ...args) => listener(...args)); } }, // From render to main and back again. invoke: (channel, args) => { let validChannels = ipc.render.sendReceive; if (validChannels.includes(channel)) { return ipcRenderer.invoke(channel, args); } } } );
Jika anda memerlukan bantuan memahami pelaksanaan saluran IPC dan cara menghantar/menerimanya dalam utas utama atau render thread, cuma tanya soalan baharu.