人人都会AI编程

9.4 多窗口管理

更新时间:2026-07-11

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_topparent 窗口句柄模拟。
  • 多屏幕适配:使用 tauri::Window::current_monitor() 获取当前显示器信息,确保窗口位置合理。

总结:多窗口管理在 Tauri 中非常直观,API 设计清晰,且受益于 Rust 的进程模型,资源开销可控。只要遵循“按需创建、合理销毁、事件通联”的原则,就能开发出流畅的多界面桌面应用。