📝 打造一个 Markdown 编辑器:Electron 项目实战教程
在现代桌面应用开发中,Electron 成为前端工程师开发跨平台工具的首选。本教程将通过一个完整示例,手把手带你构建一个功能完整的 Markdown 编辑器。
🎯 项目目标
实现一个支持以下功能的桌面 Markdown 编辑器:
- 实时 Markdown 预览
- 支持本地文件打开与保存
- 自动同步编辑与预览内容
- 跨平台运行(Windows/macOS/Linux)
📦 技术栈
- Electron
- Node.js + fs 模块
- Marked(Markdown 转换库)
- DOMPurify(防止 XSS)
- HTML/CSS/JavaScript 原生开发(可拓展 Vue/React)
📁 项目结构
markdown-editor/
├── main.js # 主进程入口
├── preload.js # 渲染与主进程通信桥梁
├── index.html # 编辑器页面
├── renderer.js # 渲染进程逻辑
├── style.css # 页面样式
├── package.json
🧱 第一步:初始化项目
bash
mkdir markdown-editor && cd markdown-editor
npm init -y
npm install electron marked dompurify
package.json 添加启动脚本:
json
"scripts": {
"start": "electron ."
}
🧠 第二步:主进程 main.js
js
const { app, BrowserWindow, dialog, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
function createWindow() {
const win = new BrowserWindow({
width: 1000,
height: 700,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
}
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
// 文件保存逻辑
ipcMain.handle('save-file', async (event, content) => {
const { filePath } = await dialog.showSaveDialog({
filters: [{ name: 'Markdown', extensions: ['md'] }]
});
if (filePath) fs.writeFileSync(filePath, content);
});
// 文件打开逻辑
ipcMain.handle('open-file', async () => {
const { filePaths } = await dialog.showOpenDialog({
filters: [{ name: 'Markdown', extensions: ['md'] }],
properties: ['openFile']
});
if (filePaths[0]) return fs.readFileSync(filePaths[0], 'utf-8');
});
🌉 第三步:preload.js(暴露通信接口)
js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
saveFile: (content) => ipcRenderer.invoke('save-file', content),
openFile: () => ipcRenderer.invoke('open-file')
});
🧑🎨 第四步:HTML 页面 index.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Markdown Editor</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<button id="open">📂 打开</button>
<button id="save">💾 保存</button>
</header>
<main>
<textarea id="editor" placeholder="输入 Markdown 内容..."></textarea>
<div id="preview"></div>
</main>
<script src="renderer.js"></script>
</body>
</html>
🎨 第五步:CSS 样式 style.css
css
body { margin: 0; font-family: sans-serif; display: flex; flex-direction: column; height: 100vh; }
header { padding: 10px; background: #282c34; color: white; display: flex; gap: 10px; }
main { flex: 1; display: flex; }
textarea, #preview { flex: 1; padding: 1rem; border: none; outline: none; font-size: 1rem; }
textarea { resize: none; }
#preview { background: #f7f7f7; overflow-y: auto; }
⚙️ 第六步:渲染逻辑 renderer.js
js
const editor = document.getElementById('editor');
const preview = document.getElementById('preview');
const marked = require('marked');
const DOMPurify = require('dompurify');
editor.addEventListener('input', () => {
const raw = marked.parse(editor.value);
preview.innerHTML = DOMPurify.sanitize(raw);
});
document.getElementById('save').addEventListener('click', () => {
window.electronAPI.saveFile(editor.value);
});
document.getElementById('open').addEventListener('click', async () => {
const content = await window.electronAPI.openFile();
if (content) {
editor.value = content;
const raw = marked.parse(content);
preview.innerHTML = DOMPurify.sanitize(raw);
}
});
🚀 启动项目
bash
npm start
你将看到一个拥有基本 Markdown 编辑功能的桌面应用,支持打开 .md
文件,编辑后保存,预览区实时渲染内容。
🔧 可拓展功能建议
- 添加文件拖拽上传功能
- 使用 Vue/React 重构渲染层
- 自动保存 & 恢复
- 支持主题切换(浅色/暗色)
- 导出 PDF/HTML
✅ 总结
通过本教程你掌握了:
- 如何搭建一个完整的 Electron 应用;
- 使用
ipcRenderer
与ipcMain
实现文件交互; - 利用
marked
+DOMPurify
实现 Markdown 渲染与防注入; - 构建一个跨平台可用的 Markdown 编辑器。