本附录为从 Electron 转向 Tauri 的开发者提供常用 API 的对照参考。Tauri 的架构与 Electron 相似,但后端使用 Rust,前端通过 IPC 调用系统能力。所有示例均基于 Tauri 2.x。
A.1 应用生命周期
| 功能 | Electron | Tauri |
|------|----------|-------|
| 应用启动 | app.whenReady().then(...) | tauri::Builder::default().setup(...) 或前端监听 onMounted |
| 应用退出 | app.quit() | 前端调用 import { exit } from '@tauri-apps/plugin-process';Rust 端 std::process::exit(0) |
| 窗口全部关闭时退出 | app.on('window-all-closed', ...) | Rust 中设置 on_window_event 闭包,或 tauri.conf.json 中 app.withGlobalTauri: true |
| 获取应用路径 | app.getPath('userData') | Rust 端 app.path().app_data_dir() 返回 PathBuf |
Tauri 关键代码片段(Rust):
tauri::Builder::default()
.setup(|app| {
let data_dir = app.path().app_data_dir()?;
println!("应用数据目录: {:?}", data_dir);
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
A.2 窗口管理
Tauri 通过 tauri::WebviewWindowBuilder 或前端包 @tauri-apps/api/window 管理窗口。
| 操作 | Electron | Tauri |
|------|----------|-------|
| 创建窗口 | new BrowserWindow(options) | Rust: WebviewWindowBuilder::new(app, "label", url).build()?; |
| 关闭窗口 | win.close() | 前端: import { getCurrentWindow } from '@tauri-apps/api/window'; getCurrentWindow().close(); |
| 最小化/最大化 | win.minimize() / win.maximize() | getCurrentWindow().minimize() / toggleMaximize() |
| 全屏切换 | win.setFullScreen(flag) | getCurrentWindow().setFullscreen(true) |
| 窗口置顶 | win.setAlwaysOnTop(flag) | getCurrentWindow().setAlwaysOnTop(true) |
| 设置窗口大小 | win.setSize(width, height) | getCurrentWindow().setSize(new LogicalSize(800, 600)) |
| 监听窗口事件 | win.on('resize', ...) | getCurrentWindow().onResized(handler) |
Tauri 前端示例:
import { getCurrentWindow } from '@tauri-apps/api/window';
const appWindow = getCurrentWindow();
appWindow.setTitle('我的 Tauri 应用');
appWindow.onCloseRequested(async (event) => {
// 阻止直接关闭,可以弹确认对话框
event.preventDefault();
});
A.3 对话框与文件系统
Tauri 提供 @tauri-apps/plugin-dialog 和 @tauri-apps/plugin-fs 插件。
| 功能 | Electron | Tauri |
|------|----------|-------|
| 打开文件对话框 | dialog.showOpenDialog(win, options) | import { open } from '@tauri-apps/plugin-dialog'; open(options) |
| 保存文件对话框 | dialog.showSaveDialog(win, options) | import { save } from '@tauri-apps/plugin-dialog'; save(options) |
| 消息框 | dialog.showMessageBox(win, options) | import { message, ask } from '@tauri-apps/plugin-dialog'; |
| 读取文本文件 | fs.readFile(filePath, 'utf-8') | import { readTextFile } from '@tauri-apps/plugin-fs'; readTextFile(filePath) |
| 写入文本文件 | fs.writeFile(filePath, data) | import { writeTextFile } from '@tauri-apps/plugin-fs'; writeTextFile(filePath, data) |
| 检查文件是否存在 | fs.existsSync(path) | import { exists } from '@tauri-apps/plugin-fs'; exists(path) |
Tauri 对话框示例:
import { open } from '@tauri-apps/plugin-dialog';
const file = await open({
multiple: false,
filters: [{ name: 'Markdown', extensions: ['md'] }]
});
if (file) {
console.log('选中文件:', file.path);
}
A.4 系统托盘与通知
| 功能 | Electron | Tauri |
|------|----------|-------|
| 创建托盘 | new Tray(icon) | tauri::tray::TrayIconBuilder 或前端 @tauri-apps/api/tray |
| 托盘菜单 | tray.setContextMenu(menu) | Rust 端构建 tauri::menu::Menu 并传给托盘 |
| 系统通知 | new Notification({ title, body }).show() | @tauri-apps/plugin-notification 的 sendNotification |
Tauri 托盘 Rust 示例(简化):
use tauri::tray::{TrayIconBuilder, MouseButton, MouseButtonState, TrayIconEvent};
use tauri::menu::{MenuBuilder, MenuItemBuilder};
let tray_menu = MenuBuilder::new(app)
.item(&MenuItemBuilder::with_id("show", "显示").build(app)?)
.build()?;
let _tray = TrayIconBuilder::new()
.icon(app.default_window_icon().unwrap().clone())
.menu(&tray_menu)
.on_menu_event(|app, event| {
if event.id.as_ref() == "show" {
// 显示窗口
}
})
.build(app)?;
A.5 进程间通信(IPC)
Electron 使用 ipcMain / ipcRenderer,Tauri 采用 Rust 命令与事件系统。
| 通信方式 | Electron | Tauri |
|----------|----------|-------|
| 渲染进程 → 主进程(请求-响应) | ipcRenderer.invoke(channel, args) / ipcMain.handle(channel, handler) | 前端使用 import { invoke } from '@tauri-apps/api/core'; invoke('command_name', { args });Rust 端 #[tauri::command] |
| 主进程主动推送 | webContents.send(channel, data) | Rust: window.emit('event-name', payload);前端: listen('event-name', callback) |
| 渲染进程监听事件 | ipcRenderer.on(channel, callback) | import { listen } from '@tauri-apps/api/event'; listen('event-name', callback) |
Tauri 命令定义(Rust):
#[tauri::command]
fn greet(name: &str) -> String {
format!("你好, {}!", name)
}
// 在 main 中注册
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error");
Tauri 前端调用:
import { invoke } from '@tauri-apps/api/core';
const greeting = await invoke<string>('greet', { name: 'Tauri' });
console.log(greeting);
A.6 原生菜单
| 功能 | Electron | Tauri |
|------|----------|-------|
| 应用菜单 | Menu.buildFromTemplate(template) | Rust: MenuBuilder::new(app) 或使用 tauri::menu::SubmenuBuilder |
| 上下文菜单 | window.webContents.on('context-menu', handler) | Rust 监听窗口事件或前端使用 @tauri-apps/api/menu (v2) |
A.7 自动更新
| 功能 | Electron | Tauri |
|------|----------|-------|
| 自动更新 | electron-updater 模块 | @tauri-apps/plugin-updater |
| 检查更新 | autoUpdater.checkForUpdates() | import { check } from '@tauri-apps/plugin-updater'; check() |
| 下载更新 | 自动或手动 | update.downloadAndInstall() |
Tauri 更新示例:
import { check } from '@tauri-apps/plugin-updater';
const update = await check();
if (update) {
await update.downloadAndInstall();
// 需要重启应用
}
A.8 打包与配置
| 概念 | Electron | Tauri |
|------|----------|-------|
| 配置文件 | 无统一标准,常用 electron-builder.yml | tauri.conf.json |
| 图标生成 | 手动提供多尺寸图片 | tauri icon 命令从单张源图生成所有平台图标 |
| 跨平台构建 | 本地逐平台构建或 CI 多平台矩阵 | tauri build --target universal-apple-darwin 等,CI 配置简单 |
| 包体积 | 约 100 MB+ | 约 3 MB 起(不含框架运行时) |
A.9 安全模型对比
| 方面 | Electron | Tauri |
|------|----------|-------|
| 渲染进程权限 | 默认可访问 Node.js(旧版),现代推荐 contextIsolation | 前端 Webview 完全不提供系统 API,必须通过命令调用 |
| IPC 安全 | contextBridge 暴露白名单方法 | Rust 命令天然函数级白名单,前端只能调用注册的命令 |
| CSP | 需手动设置 | 可通过 tauri.conf.json 配置 CSP 头 |
| 深度链接 | 需手动处理 app.setAsDefaultProtocolClient | 插件 tauri-plugin-deep-link |
这份速查表覆盖了从 Electron 过渡到 Tauri 时最常用的核心 API。Tauri 的哲学是将系统能力封装为一个个插件,前端只暴露必需接口,从而实现更小的包体与更强的安全性。实际开发中,建议配合 Tauri 官方文档和插件市场(crates.io 及 @tauri-apps 作用域)查阅详细用法。