1. 创建新窗口
从 Rust 后端创建:
使用 tauri::WebviewWindowBuilder 可以精细控制窗口参数。
use tauri::WebviewWindowBuilder;
#[tauri::command]
fn open_settings(app: tauri::AppHandle) {
WebviewWindowBuilder::new(&app, "settings", tauri::WebviewUrl::App("settings.html".into()))
.title("设置")
.inner_size(600.0, 400.0)
.resizable(false)
.build()
.unwrap();
}
从前端 JavaScript 创建:
借助 @tauri-apps/api 中的 WebviewWindow 类直接调用。
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
const settingsWin = new WebviewWindow('settings', {
url: 'settings.html',
title: '设置',
width: 600,
height: 400,
resizable: false
});
两种方式效果等价,选择哪个取决于逻辑归属:如果窗口创建需要结合 Rust 侧的资源或权限校验,放在后端更合适;纯前端驱动的交互,用前端 API 更便捷。
2. 窗口标签与 URL 路由
每个窗口都有一个唯一的 label,用作后续操作的标识。窗口加载的 URL 可以是:
- 应用内页面(
App模式),如settings.html,对应前端构建产物中的同名文件; - 外部地址(
External模式),需在tauri.conf.json中开启对应权限; - 自定义协议或嵌入式页面(如
tauri://localhost)等。
注意:如果多个窗口加载同一个 URL,它们会拥有各自独立的 WebView 实例,共享 Rust 后端进程,但前端状态完全隔离(除非通过后端交换数据)。
3. 窗口生命周期管理
创建窗口后,可以通过其句柄进行显示、隐藏、关闭、聚焦等操作。
Rust 侧示例:
let win = app.get_webview_window("settings").unwrap();
win.show().unwrap();
win.set_focus().unwrap();
前端侧示例:
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
const win = WebviewWindow.getByLabel('settings');
win?.show();
win?.setFocus();
监听窗口关闭事件(Rust 侧):
win.once("close-requested", |_| {
// 清理资源
true // 返回 true 允许关闭,false 阻止关闭
});
4. 窗口间通信
多窗口场景下,窗口之间的数据协同至关重要。推荐两种方式:
a) 通过 Rust 事件系统
所有窗口都能监听和触发全局事件,这是一种松耦合的通信方式。
前端 A 发出事件:
import { emit } from '@tauri-apps/api/event';
emit('sync-data', { payload: 'hello' });
前端 B 监听:
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('sync-data', (event) => {
console.log(event.payload);
});
Rust 侧同样可以参与事件收发,适合业务逻辑集中调度。
b) 通过 Rust 状态共享
利用 Tauri 的 state 管理,多个窗口可以读取同一个全局数据。当数据变更时,需要主动通知其他窗口刷新(可通过事件或轮询实现)。
不建议:直接通过前端全局变量共享,因为每个窗口是独立的 WebView 上下文。
5. 内存与性能注意事项
虽然 Tauri 多窗口比 Electron 轻量很多,但仍需规划:
- 每个 WebView 都会占用独立的渲染内存,通常每个窗口额外增加 10~30 MB(视前端复杂度而定)。
- 如果多个窗口内容相似(如多个文档视图),可考虑在同一窗口内用前端路由模拟多标签页,减少渲染进程数量。
- 确保不再使用的窗口完全销毁(
close()),而不是仅仅隐藏,以释放内存。
配置复用:在 tauri.conf.json 中可通过 windows 数组预定义公用窗口配置,减少重复代码。
6. 实际开发建议
- 窗口关系:如果子窗口需要跟随父窗口关闭,可在主窗口的
close-requested事件中按需关闭子窗口。 - 模式窗口:Tauri 暂未内置模态窗口支持,但可通过设置
always_on_top和parent窗口句柄模拟。 - 多屏幕适配:使用
tauri::Window::current_monitor()获取当前显示器信息,确保窗口位置合理。
总结:多窗口管理在 Tauri 中非常直观,API 设计清晰,且受益于 Rust 的进程模型,资源开销可控。只要遵循“按需创建、合理销毁、事件通联”的原则,就能开发出流畅的多界面桌面应用。