Tauri 常见注意项:首屏、窗口与交互细节
前言
桌面端 Tauri 启动时,系统会先拉起 WebView 再加载前端资源,主窗口若过早露出,首屏容易出现白屏或半渲染界面。
本文说明如何在 Tauri 2 里把主窗先藏起来、等首屏就绪再显示,以及如何配置或代码居中窗口,并用 CSS 减少界面文字被误选。
进一步覆盖无边框时的标题栏与拖拽区划分、深浅色与系统主题协同,以及最小化到托盘、关闭与退出的常见交互分工。
另补充系统字体栈、字号与缩放感知,以及将文件拖入指定区域并给出校验失败时的明确提示,便于批处理类工具落地。
不展开路由框架细节,示例以前端调用 @tauri-apps/api 为主;涉及托盘时补充少量 Rust 与 capability 配置。
依赖与版本号请与你仓库里的 package.json 及 Cargo.toml 对齐;若项目基于更早的 Tauri 大版本,请以该版本文档为准替换接口与配置名称。
依赖
本节不新增必选 Rust crate,主要依赖 Tauri 官方的前端 API 包。
脚手架生成的项目里,package.json 通常已声明 @tauri-apps/api。
下面是一条最小依赖示例,版本号请改为你本地已锁定的范围。
1 | { |
首次拉包或改依赖后,需要在项目根目录安装依赖。
下面命令在项目根执行,用于安装或同步 node_modules。
1 | npm install |
若启用下文「托盘」中的系统托盘,需要在 src-tauri/Cargo.toml 为 tauri 打开 tray-icon 特性;若已有 features = [...],请将 tray-icon 并入该数组而不是另起一行覆盖。
1 | [dependencies] |
加载后显示
思路是进程启动时先不露出主窗,等首屏脚本跑完(或路由首屏挂载完成)再调用窗口 API,让白屏留在不可见阶段。
在 src-tauri/tauri.conf.json 的 app.windows 里为主窗口设置 visible: false,可在进程启动阶段就避免窗口闪现未完成界面。
下面 JSON 表示标签为 main 的窗口初始不可见;具体字段以你本地的 JSON Schema 或官方文档为准。
1 | { |
前端在页面就绪后再调用 show() 露出窗口;下面在浏览器 DOMContentLoaded 后获取当前窗口并执行 show()。
你也可以把同样逻辑放进 Vue 的 onMounted、React 的 useEffect 等位置。
1 | import { getCurrentWindow } from "@tauri-apps/api/window"; |
若还需要在显示前拉取配置或鉴权,只要在 await show() 之前插入你的异步逻辑即可。
居中
在 tauri.conf.json 的同一窗口项上可开启 center: true,尽量在创建时把窗口放到屏幕中央。
可与上一节的 visible: false 写在同一窗口配置里一并使用。
下面片段在窗口对象上同时关闭初始可见性并启用居中。
1 | { |
有时仅靠配置不够稳定,尤其在多显示器或动态改尺寸的场景,你可以在 lib.rs 的 Builder setup 钩子里对主窗口再调用一次 center()。
下面在 main 中与 run 链式组合,于 setup 阶段获取 main 窗口并居中;入口路径需与你项目模板一致。
1 | use tauri::Manager; |
禁止选择
桌面 WebView 里拖动鼠标容易选中整段界面文案,工具类、仪表盘类界面常希望禁止选择。
用 CSS 在根节点关闭 user-select 即可;需要复制或编辑的区域(输入框、contenteditable、可选中代码块)再单独允许选择,避免影响表单与无障碍需求。
下面是一段可放在全局样式或根组件中的示例,按需合并进你的样式体系。
1 | html, |
若个别控件仍被选中文案,可检查是否被更具体的选择器覆盖了上述规则,或为该类节点单独写上 user-select: none。
标题栏
无边框窗口需要自绘顶栏,并用 data-tauri-drag-region 标出可拖拽区域,否则用户无法移动窗口。
官方推荐把「可拖区域」与「可点按钮」拆成并列结构:拖拽放在一块区域,最小化、最大化、关闭放在另一块,避免点击被当成拖拽。
在 tauri.conf.json 对应窗口上关闭系统装饰,才能完全自绘标题栏。
下面只标出 decorations 字段,请合并进你已有的 windows 条目,勿覆盖其它宽高与可见性配置。
1 | { |
启用拖拽与窗口控制命令前,需在 capability 里放行窗口相关权限;下列为常见组合,若你精简过权限表,请按运行报错逐项补齐。
1 | { |
下面 HTML 将标题文本放在带 data-tauri-drag-region 的区域,关闭按钮单独占位;布局可按设计改为左侧拖拽、右侧按钮等。
1 | <header class="titlebar"> |
顶栏需要固定高度并禁止文本选中,避免拖动时误选;下面给出与结构配套的最小样式。
1 | .titlebar { |
使用 @tauri-apps/api/window 把关闭按钮接到窗口 API;若需双击标题栏切换最大化,可查阅官方「窗口定制」里基于 startDragging 的手动实现。
1 | import { getCurrentWindow } from "@tauri-apps/api/window"; |
若子元素必须叠放在同一块拖拽区域内,可查阅当前 Tauri 版本文档中关于 data-tauri-drag-region 排除子节点的写法(例如排除属性或 false 取值),以免按钮无法点击。
主题
页面侧可用 prefers-color-scheme 切换配色;若希望窗口边框、标题栏等系统壳层与系统一致,可在前端对当前窗口使用 setTheme 与 onThemeChanged。
在 Windows 与较新的 macOS 上,窗口主题会影响 WebView 内 prefers-color-scheme 的取值。
Linux 上行为可能与桌面环境相关,以本机实测为准。
下面在启动时订阅系统主题变化,并把主题枚举同步到 document.documentElement 的 data-theme,供 CSS 变量或选择器使用。
1 | import { getCurrentWindow } from "@tauri-apps/api/window"; |
若你希望显式跟随系统而不是写死深浅色,可对当前窗口传入 null 作为主题,由系统决定壳层与 prefers-color-scheme;具体可调用形式以你锁定的 @tauri-apps/api 类型定义为准。
1 | import { getCurrentWindow } from "@tauri-apps/api/window"; |
也可以在 Rust 的 setup 里对 WebviewWindow 调用 set_theme,与前端二选一或配合使用;平台支持与枚举名请以 docs.rs 上与你版本一致的 tauri 文档为准。
托盘
下载器、同步类应用常把「点关闭」做成隐藏主窗而非退出进程,并通过托盘图标再次打开;真正退出放在托盘菜单或设置里,避免用户找不到后台任务。
下面假设已在依赖里启用 tray-icon 特性;托盘与菜单的权限以你当前 Tauri 版本的 ACL 默认集成为准,若创建失败请对照官方「系统托盘」与「权限」文档补全 capability。
调用 hide 通常需要在 capability 中显式加入 core:window:allow-hide,该权限往往不在 core:window:default 内。
前端创建托盘图标并挂菜单,其中「退出」通过 invoke 调用你在 Rust 注册的命令结束进程;show 用于从托盘回到主窗。
1 | import { TrayIcon } from "@tauri-apps/api/tray"; |
在 Rust 侧注册 quit_app 命令,在内部调用 AppHandle::exit;再把它挂进你项目里已有的 tauri::Builder 链,例如与居中一节使用的 setup 写在同一个 generate_handler 列表中。
1 |
|
在你现有 Builder 链上追加 invoke_handler,或把 quit_app 合并进已有的 generate_handler! 宏参数列表。
1 | .invoke_handler(tauri::generate_handler![quit_app]) |
若 invoke("quit_app") 在运行时提示权限或命令未注册,请核对 capability 是否允许该命令,以及 generate_handler 是否包含 quit_app。
若你希望关闭即真退出而非隐藏,可去掉 onCloseRequested 中的 preventDefault,或仅在用户勾选「最小化到托盘」时注册该监听。
托盘与窗口组合行为在不同操作系统上略有差异,发布前建议在 Windows、macOS 与目标 Linux 发行版上各测一轮。
字体
跨平台桌面端应尽量跟随系统 UI 字体,避免写死某一端专用字体名导致在其它系统回退不佳。
正文与界面字号优先用 rem 相对根元素,由用户在系统里调整「缩放与布局」时,整体比例更容易一致。
Windows 高分屏与自定义缩放比例下,若整页被 CSS transform 非整数缩放,文字与细线容易发糊;关键布局尽量少依赖根级缩放,边框宽度尽量用逻辑像素整数或 hairline 策略。
下面给出常见系统字体栈与根字号示例,可按品牌规范替换西文部分、保留 system-ui 与平台回退。
1 | :root { |
需要与系统缩放联动排障或做精细布局时,可对当前窗口读取 scaleFactor,或在缩放变化时更新 CSS 变量。
下面订阅缩放变化并写入 --sf,供你在样式中按需参与计算(不必强行使用)。
1 | import { getCurrentWindow } from "@tauri-apps/api/window"; |
拖入
批处理、导入类功能常要把文件拖到窗口内固定区域;用 Tauri 的 onDragDropEvent 能拿到系统给出的路径列表,比单纯依赖 DOM 的 drop 更贴近桌面端行为。
请在界面上画出明确的「拖放命中区」,并在校验失败时用文案或轻提示说明原因(扩展名不符、数量超限等),避免静默失败。
若收不到事件,请在 tauri.conf.json 对应窗口上确认 dragDropEnabled 为 true;官方说明默认一般为开启,仅在需要改用页面内 HTML5 拖放时再在 Windows 上关闭。
下面片段仅标出该字段,请合并进已有窗口配置。
1 | { |
下面用一块带固定 class 的落点区域配合 getCurrentWebview 监听拖放。drop 时只做扩展名校验与提示,真实读文件可再接 fs 插件或 Rust 命令。
1 | <section class="drop-panel" aria-label="将文件拖到此处"> |
上面结构把命中区与错误提示分成独立节点,便于屏幕阅读器与后续样式控制。
下面样式用虚线框与最小高度强调落点;使用了 color-mix 与系统颜色关键字,若目标 WebView 较旧可改回固定十六进制色。
1 | .drop-panel { |
事件监听使用 @tauri-apps/api/webview 的 getCurrentWebview;载荷类型为 enter、over、leave、drop,其中 leave 表示悬停结束,用来去掉高亮。
下面在 enter 与 over 时点亮落点区,在 leave 时还原,在 drop 时校验后缀并写入 #drop-error。
1 | import { getCurrentWebview } from "@tauri-apps/api/webview"; |
若你需要「只有落在矩形区域内才算命中」,可把 over 里的坐标与 panel.getBoundingClientRect() 对比,并注意与 scaleFactor、窗口坐标系的换算,细节以当前 @tauri-apps/api 的类型定义为准。
启用 dragDropEnabled 后,可能与页面内纯文本等其它拖放来源冲突,若遇此类问题请查阅当前版本的已知限制与社区讨论。