Arkitekturer for flere vinduer
Utform og implementer komplekse Electron-applikasjoner med flere vinduer, og administrer kommunikasjon og state mellom vinduene effektivt.
Arkitekturer for flere vinduer er en gratis leksjon i Utvikling av Electron-skrivebordsapper på CoddyKit. Dette er leksjon 1 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Utvikling av Electron-skrivebordsapper, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Utvikling av Electron-skrivebordsapper inneholder totalt 4 leksjoner.
Hvorfor flere vinduer?
Electron-applikasjoner kan ofte dra nytte av flere vinduer. Tenk på en chatapplikasjon: De kan ha en hovedliste over kontakter og separate vinduer for hver aktive samtale.
- Separate arbeidsflyter: Skill oppgaver i egne vinduer.
- Brukerinnstillinger: Et innstillingsvindu som er adskilt fra hovedapplikasjonen.
- Hjelpeverktøy: Egne visningsprogrammer, inspektører eller sidepaneler.
- Bedre brukeropplevelse: Gir fleksibilitet og struktur i komplekse apper.
Opprette et nytt vindu
Å opprette flere vinduer i Electron ligner på å opprette det første hovedvinduet. De oppretter ganske enkelt en ny BrowserWindow i hovedprosessen.
Slik kan De opprette et nytt vindu som laster inn en annen HTML-fil.
const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
let secondWindow;
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
mainWindow.loadFile('index.html');
}
function createSecondWindow() {
secondWindow = new BrowserWindow({
width: 400,
height: 300,
parent: mainWindow, // Optional: make it a child window
modal: false, // Optional: for modal behavior
show: false, // Don't show immediately
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload_second.js')
}
});
secondWindow.loadFile('second.html');
secondWindow.once('ready-to-show', () => {
secondWindow.show();
});
}
app.whenReady().then(() => {
createMainWindow();
createSecondWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createMainWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});Innhold for flere vinduer
Hver BrowserWindow-instans laster inn sitt eget innhold, vanligvis en HTML-fil. Dette lar Dem utforme helt uavhengige brukergrensesnitt for ulike deler av applikasjonen.
For eksempelet ovenfor trenger De:
index.html: Grensesnittet til hovedvinduet.second.html: Det separate grensesnittet til det andre vinduet.- Tilhørende renderer- og preload-skript for hvert vindu, hvis det er nødvendig.
Administrere vindusreferanser
Når De arbeider med flere vinduer, er det viktig å holde oversikt over referansene til dem. De kan lagre dem i en tabell eller et kart, slik at De kan samhandle med bestemte vinduer senere.
Dette gjør det mulig å sende målrettede meldinger, lukke bestemte vinduer eller administrere tilstanden deres.
const { app, BrowserWindow } = require('electron');
const path = require('path');
let allWindows = []; // Array to hold references to all windows
function createNewWindow(htmlFile, width, height) {
let newWindow = new BrowserWindow({
width: width,
height: height,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js') // Can be different per window
}
});
newWindow.loadFile(htmlFile);
allWindows.push(newWindow); // Add to our list
// Remove from list when closed
newWindow.on('closed', () => {
allWindows = allWindows.filter(win => win !== newWindow);
});
return newWindow;
}
app.whenReady().then(() => {
createNewWindow('index.html', 800, 600); // Create main window
createNewWindow('second.html', 400, 300); // Create a second window
// Example: Accessing windows later
// allWindows[0].setTitle('Main App');
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});IPC fra hovedprosessen til en bestemt renderer
Hovedprosessen kan sende meldinger til en bestemt renderer-prosess ved å bruke metoden webContents.send() på den aktuelle vindusinstansen.
Dette er nødvendig for å oppdatere brukergrensesnittelementer, sende data eller utløse handlinger i et bestemt vindu.
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
let mainWindow;
let settingsWindow;
function createWindows() {
mainWindow = new BrowserWindow({
width: 800, height: 600,
webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true }
});
mainWindow.loadFile('index.html');
settingsWindow = new BrowserWindow({
width: 400, height: 300, show: false,
webPreferences: { preload: path.join(__dirname, 'preload_settings.js'), contextIsolation: true }
});
settingsWindow.loadFile('settings.html');
}
app.whenReady().then(createWindows);
// Main process sends message to settings window
ipcMain.on('open-settings', () => {
if (settingsWindow) {
settingsWindow.show();
settingsWindow.webContents.send('settings-opened', 'Welcome to settings!');
}
});
// --- Renderer (preload_settings.js) for settings.html ---
// const { ipcRenderer, contextBridge } = require('electron');
// contextBridge.exposeInMainWorld('electronAPI', {
// onSettingsOpened: (callback) => ipcRenderer.on('settings-opened', (event, message) => callback(message))
// });
// --- Renderer (settings.html script) ---
// window.electronAPI.onSettingsOpened((msg) => {
// document.getElementById('message').innerText = msg;
// });Renderer til hovedprosess (identifisere avsenderen)
Når en renderer-prosess sender en melding til hovedprosessen via ipcRenderer.send(), mottar hovedprosessen et event-objekt.
Dette event-objektet inneholder informasjon om avsenderen, blant annet event.senderFrame eller event.sender (som er WebContents-objektet til vinduet som sendte meldingen). Dermed kan hovedprosessen identifisere hvilket vindu som sendte meldingen.
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
let windows = {}; // Store windows by an ID or name
function createWindows() {
const mainWin = new BrowserWindow({
width: 800, height: 600, title: 'Main',
webPreferences: { preload: path.join(__dirname, 'preload_main.js'), contextIsolation: true }
});
mainWin.loadFile('main.html');
windows['main'] = mainWin;
const toolWin = new BrowserWindow({
width: 400, height: 300, title: 'Tool',
webPreferences: { preload: path.join(__dirname, 'preload_tool.js'), contextIsolation: true }
});
toolWin.loadFile('tool.html');
windows['tool'] = toolWin;
}
app.whenReady().then(createWindows);
ipcMain.on('renderer-message', (event, data) => {
const senderWindow = BrowserWindow.fromWebContents(event.sender);
const senderId = Object.keys(windows).find(key => windows[key] === senderWindow);
console.log(`Message from ${senderId || 'Unknown'}: ${data}`);
senderWindow.webContents.send('main-reply', `Received from ${senderId}!`);
});
// --- preload_main.js / preload_tool.js (simplified) ---
// const { ipcRenderer, contextBridge } = require('electron');
// contextBridge.exposeInMainWorld('electronAPI', {
// sendMessage: (data) => ipcRenderer.send('renderer-message', data),
// onMainReply: (callback) => ipcRenderer.on('main-reply', (event, msg) => callback(msg))
// });
// --- main.html / tool.html script ---
// window.electronAPI.sendMessage('Hello from my window!');Kommunikasjon fra renderer til renderer
Renderer-prosesser kan ikke kommunisere direkte med hverandre. All kommunikasjon mellom prosesser (IPC) må formidles av hovedprosessen.
Det betyr at en melding fra én renderer går til hovedprosessen, som deretter videresender den til renderer-prosessen som skal motta den. Dette sentraliserer kommunikasjonen og gir bedre sikkerhet.
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
let windowA, windowB;
function createWindows() {
windowA = new BrowserWindow({
width: 600, height: 400, title: 'Window A',
webPreferences: { preload: path.join(__dirname, 'preload_a.js'), contextIsolation: true }
});
windowA.loadFile('window_a.html');
windowB = new BrowserWindow({
width: 600, height: 400, title: 'Window B',
webPreferences: { preload: path.join(__dirname, 'preload_b.js'), contextIsolation: true }
});
windowB.loadFile('window_b.html');
}
app.whenReady().then(createWindows);
// Renderer A sends to Main, Main relays to Renderer B
ipcMain.on('message-from-a', (event, message) => {
console.log('Main received from A:', message);
if (windowB) {
windowB.webContents.send('message-to-b', `Relayed from A: ${message}`);
}
});
// Renderer B sends to Main, Main relays to Renderer A
ipcMain.on('message-from-b', (event, message) => {
console.log('Main received from B:', message);
if (windowA) {
windowA.webContents.send('message-to-a', `Relayed from B: ${message}`);
}
});
// --- preload_a.js (example) ---
// const { ipcRenderer, contextBridge } = require('electron');
// contextBridge.exposeInMainWorld('electronAPI', {
// sendToB: (msg) => ipcRenderer.send('message-from-a', msg),
// onMessageFromB: (callback) => ipcRenderer.on('message-to-a', (event, msg) => callback(msg))
// });
// --- window_a.html script ---
// window.electronAPI.sendToB('Hello from Window A!');Administrere delt tilstand
Når De har flere vinduer, trenger de ofte tilgang til eller deling av de samme dataene. Her er noen vanlige strategier:
- Hovedprosessen som sannhetskilde: Lagre delte data i hovedprosessen, og bruk IPC til å be om eller oppdatere dem fra renderer-prosessene.
- Electron Store: En enkel plattformuavhengig løsning for å lagre brukerinnstillinger og applikasjonstilstand.
- IPC for datasynkronisering: Renderer-prosessene varsler hovedprosessen om endringer, og hovedprosessen kringkaster oppdateringer til andre berørte renderer-prosesser.
- Globalt objekt (vær forsiktig!): I enkelte enkle tilfeller kan et globalt JavaScript-objekt i hovedprosessen inneholde delt tilstand, men dette kan bli uoversiktlig i komplekse apper.
Beste praksis for flere vinduer
Utforming av applikasjoner med flere vinduer krever grundige vurderinger:
- Minnebruk: Hver
BrowserWindower en separat Chromium-instans som bruker minne. Begrens unødvendige vinduer. - Livssyklusadministrasjon: Avgjør om lukking av et undervindu skal påvirke foreldrevinduet eller hovedapplikasjonen.
- Brukeropplevelse: Gi tydelig navigering mellom vinduene. Ta hensyn til vindusplassering, og husk brukerens innstillinger.
- Feilhåndtering: Implementer robust feilhåndtering for IPC og vindushendelser for å hindre krasj.
- Isolering av kontekst: Aktiver alltid
contextIsolation, og bruk preload-skript for sikker eksponering av API-er, særlig når De har flere vinduer.
Kontroll av IPC for flere vinduer
De har to renderer-prosesser, Renderer A og Renderer B. Renderer A må sende en melding til Renderer B. Hvordan bør denne kommunikasjonen struktureres i Electron?
Oppsummering: Arkitekturer med flere vinduer
Gratulerer! De har lært hvordan De utformer og implementerer Electron-applikasjoner med flere vinduer.
Vi har gått gjennom hvordan De oppretter flere BrowserWindow-instanser, administrerer referansene deres og implementerer sikker kommunikasjon mellom vinduer via hovedprosessen. De har også utforsket strategier for delt tilstand og beste praksis for å bygge komplekse skrivebordsopplevelser med flere vinduer.
Lær deg JavaScript med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 12
- Leksjoner
- 47
Ofte stilte spørsmål
Er leksjonen «Arkitekturer for flere vinduer» gratis?
Ja – hele teksten i «Arkitekturer for flere vinduer» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Utvikling av Electron-skrivebordsapper-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Utvikling av Electron-skrivebordsapper inneholder totalt 4 leksjoner.
Hva lærer jeg i «Arkitekturer for flere vinduer»?
Utform og implementer komplekse Electron-applikasjoner med flere vinduer, og administrer kommunikasjon og state mellom vinduene effektivt. Du øver på Utvikling av Electron-skrivebordsapper med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Utvikling av Electron-skrivebordsapper?
Ingen tidligere erfaring er nødvendig. Utvikling av Electron-skrivebordsapper på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.
Hvor lang tid tar leksjonen «Arkitekturer for flere vinduer»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Utvikling av Electron-skrivebordsapper-leksjonen?
Ja. Alle Utvikling av Electron-skrivebordsapper-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Arkitekturer for flere vinduer
- Bakgrunnsprosesser og workers
- Integrasjon med skytjenester
- Automatiske oppdateringer av Electron-appen