Aug 20, 2025
2 min read
Rust,
Tauri,

Tauri 开发实战:超越文档的窗口管理和跨平台经验

本文分享了在使用 Tauri 开发桌面应用时遇到的一些实际问题和解决方案,包括动态窗口检测、菜单栏隐藏与自定义窗口控制、三大平台(Windows/macOS/Linux)的差异处理,以及 Tauri 与 Dioxus 的开发体验对比。

动态窗口检测

创建动态窗口要检查窗口是否已经存在,原因是 webview 窗口是通过 label(我不太了解 webview 的命名惯例,理论上这应该叫 id,但是至少在 tauri 的 api 里就叫 label) 作为窗口唯一 ID,如果不做判断,在已经存在了同样名称的窗口的情况下肯定会报错:

called `Result::unwrap()` on an `Err` value: WebviewLabelAlreadyExists("setting")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

隐藏菜单栏

某些界面需要隐藏菜单栏,但是 tauri 只有decorations = false 这个方案,这个方案会把窗体装饰(包括标题,最大化最小化窗口)和菜单栏一起隐藏掉。 这个操作也会会造成窗体无法移动了。

我的解决方案还是用 decorations = false,然后在界面中模拟标题以及关闭窗口、最大化最小化窗口等。

<span data-tauri-drag-region className="dark:text-zinc-200 font-medium text-center">我是窗口标题</span>

通过添加 data-tauri-drag-region 来解决窗口无法移动的问题。但是如果你把data-tauri-drag-region 加到顶层的结构上有可能是无效的,具体原因我猜应该和一些事件冲突了。

至少最大化、最小化、关闭窗口的模拟,使用以下API 即可:

	const currentWindow = WebviewWindow.getCurrent();
	await currentWindow.close(); //关闭
	await currentWindow.minimize(); // 最小化
	await currentWindow.hide(); //隐藏
	await currentWindow.maximize(); //最大化

三大平台的差异

跨平台看起来美好,多端共用一份代码,一个程序员顶仨来用。 但是其实要看你做的应用和平台的关联度有多高。比如你做一个微信,做一个飞书,用跨平台的框架大概共用的代码是非常高的。

但是如果你要做一个比如截图应用,或者录屏软件之类的,那可就不一定了。比如 macOS 在这方面是需要权限申请的,又比如 Linux, 你到底是用 X server 呢还是用 Wayland 呢? 还是都得兼容呢? 由于三大平台的接口是必须的不相同,所以必然地要写三份代码。

还有窗口差异,虽然 Tauri 是用前端写界面,但是Window 本身的窗口默认用是系统 UI。比如,Linux 下使用的是 GTK。 由于三大平台的 UI 并不一致,所以默认情况下,实现出来的应用还是有差异的。

其他的感想 由于我刚好又会前端,使用感受 Tauri 开发 GUI 实在是太方便了。使用 Tauri 的开发体验完全掉打一切原生的框架。 但是 Tauri 也很慢,响应很慢,有一种响应跟不上操作的滞后感。

如果你不会前端,其实可以使用 dioxus。dioxus 也和 Tauri 一样,使用 webview 来渲染用户界面。只是 dioxus 自己实现了一套 dsl 宏(类似于 jsx 的 RSX 语法)来写前端,对 只会 rust 的用户会友好很多。只是自由度肯定是不如 Tauri 的,Tauri 可以选择任意的 UI 库,dioxus 就只能自己来了。