Electron Practical Project
Through hands-on projects, you can deepen your understanding of various Electron features, including window management, IPC communication, file operations, data storage, and interface optimization.
Project 1: Desktop Notes App
Feature design
- Create, edit, and delete notes
- Auto-save and local storage
- Support multi-window simultaneous editing
- Clean interface, provides Markdown rendering
Technology selection
- Frontend framework: Vue or React
- Renderer process: Displays note content, supports rich text / Markdown
- Data storage:
electron-storeSave note data - main process: Manage windows, menus, and keyboard shortcuts
- IPC Communication: The renderer process requests the main process to read or save data
Implementation steps
1. Create an Electron project
mkdir electron-notes cd electron-notes npm init -y npm install electron electron-store
2. Main process main.js
Example
const { app, BrowserWindow, ipcMain } = require('electron')
const Store = require('electron-store')
const store = new Store()
let mainWindow
app.whenReady().then(() => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: `${__dirname}/preload.js`
}
})
mainWindow.loadFile('index.html')
})
// IPC: Read notes
ipcMain.handle('get-notes', () => store.get('notes', []))
// IPC: Save notes
ipcMain.handle('save-notes', (event, notes) => store.set('notes', notes))
const Store = require('electron-store')
const store = new Store()
let mainWindow
app.whenReady().then(() => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: `${__dirname}/preload.js`
}
})
mainWindow.loadFile('index.html')
})
// IPC: Read notes
ipcMain.handle('get-notes', () => store.get('notes', []))
// IPC: Save notes
ipcMain.handle('save-notes', (event, notes) => store.set('notes', notes))
3、Preload script preload.js
Example
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('api', {
getNotes: () => ipcRenderer.invoke('get-notes'),
saveNotes: (notes) => ipcRenderer.invoke('save-notes', notes)
})
contextBridge.exposeInMainWorld('api', {
getNotes: () => ipcRenderer.invoke('get-notes'),
saveNotes: (notes) => ipcRenderer.invoke('save-notes', notes)
})
4. Renderer process index.html
Example
<!DOCTYPE html>
<html>
<body>
<textarea id="note"></textarea>
<button id="saveBtn">Save</button>
<script>
const textarea = document.getElementById('note')
const btn = document.getElementById('saveBtn')
window.api.getNotes().then(notes => {
textarea.value = notes.join('\n\n')
})
btn.addEventListener('click', async () => {
await window.api.saveNotes([textarea.value])
alert('Saved successfully')
})
</script>
</body>
</html>
<html>
<body>
<textarea id="note"></textarea>
<button id="saveBtn">Save</button>
<script>
const textarea = document.getElementById('note')
const btn = document.getElementById('saveBtn')
window.api.getNotes().then(notes => {
textarea.value = notes.join('\n\n')
})
btn.addEventListener('click', async () => {
await window.api.saveNotes([textarea.value])
alert('Saved successfully')
})
</script>
</body>
</html>
Code explanation
electron-store: Responsible for local data storage, automatically serializes JSONipcMain.handle/ipcRenderer.invoke: Implement communication between the renderer process and the main processcontextBridge: Securely exposes APIs to the renderer processtextarea+Button: Simply implement note content editing and saving
Project 2: File Manager
Interface design
- Directory tree on the left, file list on the right
- Supports file operations: create, delete, rename
- Drag and drop files to target directory
- Simple search and sort functionality
File operations implementation
- Node.js fs Module: Read, write, and delete files
- path module: Path handling
- IPC Communication: The renderer process requests the main process to perform file operations
Example
// Main process main.js
const fs = require('fs')
const path = require('path')
ipcMain.handle('read-dir', (event, dirPath) => fs.readdirSync(dirPath))
ipcMain.handle('create-file', (event, filePath) => fs.writeFileSync(filePath, ''))
ipcMain.handle('delete-file', (event, filePath) => fs.unlinkSync(filePath))
const fs = require('fs')
const path = require('path')
ipcMain.handle('read-dir', (event, dirPath) => fs.readdirSync(dirPath))
ipcMain.handle('create-file', (event, filePath) => fs.writeFileSync(filePath, ''))
ipcMain.handle('delete-file', (event, filePath) => fs.unlinkSync(filePath))
Example
// renderer process
window.api.readDir('/Users/username/Documents').then(files => {
console.log(files)
})
window.api.readDir('/Users/username/Documents').then(files => {
console.log(files)
})
Drag-and-drop functionality
- Renderer process listening
dragstartanddropEvents - Main process usage
fs.renameorfs.copyFileMove files
Example
// Renderer process drop event
const dropArea = document.getElementById('fileList')
dropArea.addEventListener('drop', (event) => {
event.preventDefault()
const filePath = event.dataTransfer.files[0].path
window.api.moveFile(filePath, targetDir)
})
const dropArea = document.getElementById('fileList')
dropArea.addEventListener('drop', (event) => {
event.preventDefault()
const filePath = event.dataTransfer.files[0].path
window.api.moveFile(filePath, targetDir)
})
Performance Optimization
- Use asynchronous reading for large directories to avoid blocking the renderer process
- File list virtualization reduces DOM rendering pressure
- Use batch updates or Web Workers for frequent operations
Summary
Through these two hands-on projects, you can master:
- Window and multi-process communication: Parent-child windows, IPC
- Local data storage:electron-store、fs
- Interface and performance optimization: Virtual list, lazy loading, asynchronous processing
- Native functionality integration: File operations, drag-and-drop, menus, and keyboard shortcuts
These projects can serve as base templates for subsequent complex desktop application development, helping to quickly build feature-rich Electron apps.
other extensions