跳到主要内容

Splashscreen

如何在 Tauri 中实现基本的启动屏(Splashscreen)功能

创建项目

创建一个 Tauri 项目,请参考创建项目

添加步骤

  1. 添加新窗口

tauri.conf.json 注册新窗口,修改 src-tauri/tauri.conf.json 文件,创建一个隐藏的 main 窗口和一个默认显示的 splashscreen 窗口:

{
"windows": [
{
"label": "main",
"visible": false
},
{
"label": "splashscreen",
"url": "/splashscreen"
}
]
}
  1. 创建一个 splashscreen 页面

在项目根目录创建一个 splashscreen.html 文件,用于展示启动屏内容:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="/src/styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri Splashscreen</title>
</head>
<body>
<div class="container">
<h1>Tauri 正在启动...</h1>
<div class="row">
<h5>请稍候,正在加载应用。</h5>
</div>
</div>
</body>
</html>
  1. 模拟前端初始化任务

前端任务:在 src/App.vue 中添加 setup 逻辑,使用 setTimeout 模拟初始化耗时任务。

import { invoke } from "@tauri-apps/api/tauri";

function sleep(seconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}

async function setup() {
console.log("正在进行前端初始化任务...");
await sleep(3);
console.log("前端初始化任务完成!");
invoke("set_complete", { task: "frontend" });
}

window.addEventListener("DOMContentLoaded", () => {
setup();
});
  1. 模拟后端初始化任务

后端任务:在 src-tauri/src/lib.rs 中使用 Tokio 进行异步任务模拟。

  • 添加 tokio 依赖:
cd src-tauri
cargo add tokio
  • lib.rs 中添加后端任务逻辑:
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
// #[tauri::command]
// fn greet(name: &str) -> String {
// format!("Hello, {}! You've been greeted from Rust!", name)
// }

// #[cfg_attr(mobile, tauri::mobile_entry_point)]
// pub fn run() {
// tauri::Builder::default()
// .plugin(tauri_plugin_shell::init())
// .invoke_handler(tauri::generate_handler![greet])
// .run(tauri::generate_context!())
// .expect("error while running tauri application");
// }

// Import functionalities we'll be using
use std::sync::Mutex;
use tauri::async_runtime::spawn;
use tauri::{AppHandle, Manager, State};
use tokio::time::{sleep, Duration};

// Create a struct we'll use to track the completion of
// setup related tasks
struct SetupState {
frontend_task: bool,
backend_task: bool,
}

// Our main entrypoint in a version 2 mobile compatible app
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
// Don't write code before Tauri starts, write it in the
// setup hook instead!
tauri::Builder::default()
// Register a `State` to be managed by Tauri
// We need write access to it so we wrap it in a `Mutex`
.manage(Mutex::new(SetupState {
frontend_task: false,
backend_task: false,
}))
// Add a command we can use to check
.invoke_handler(tauri::generate_handler![greet, set_complete])
// Use the setup hook to execute setup related tasks
// Runs before the main loop, so no windows are yet created
.setup(|app| {
// Spawn setup as a non-blocking task so the windows can be
// created and ran while it executes
spawn(setup(app.handle().clone()));
// The hook expects an Ok result
Ok(())
})
// Run the app
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

#[tauri::command]
fn greet(name: String) -> String {
format!("Hello {name} from Rust!")
}

// A custom task for setting the state of a setup task
#[tauri::command]
async fn set_complete(
app: AppHandle,
state: State<'_, Mutex<SetupState>>,
task: String,
) -> Result<(), ()> {
// Lock the state without write access
let mut state_lock = state.lock().unwrap();
match task.as_str() {
"frontend" => state_lock.frontend_task = true,
"backend" => state_lock.backend_task = true,
_ => panic!("invalid task completed!"),
}
// Check if both tasks are completed
if state_lock.backend_task && state_lock.frontend_task {
// Setup is complete, we can close the splashscreen
// and unhide the main window!
let splash_window = app.get_webview_window("splashscreen").unwrap();
let main_window = app.get_webview_window("main").unwrap();
splash_window.close().unwrap();
main_window.show().unwrap();
}
Ok(())
}

// An async function that does some heavy setup task
async fn setup(app: AppHandle) -> Result<(), ()> {
// Fake performing some heavy action for 3 seconds
println!("Performing really heavy backend setup task...");
sleep(Duration::from_secs(3)).await;
println!("Backend setup task completed!");
// Set the backend task as being completed
// Commands can be ran as regular functions as long as you take
// care of the input arguments yourself
set_complete(
app.clone(),
app.state::<Mutex<SetupState>>(),
"backend".to_string(),
)
.await?;
Ok(())
}
  1. 运行应用

执行以下命令启动应用:

pnpm tauri dev

启动后,你会看到 splashscreen 窗口显示内容,3 秒后前端和后端的初始化任务完成,splashscreen 会关闭,主窗口 main 会显示出来。

总结

  1. splashscreen 的作用是用来覆盖耗时的初始化任务,用户体验上显得更友好。
  2. 前端使用 setTimeout 模拟任务,后端使用 Tokio 异步任务模拟。
  3. 完成初始化后,通过 Tauri 的 get_webview_window 关闭启动屏并显示主窗口。

你可以根据实际需求进一步优化 UI 或初始化逻辑。如果还有问题,随时告诉我! 🚀

splashscreen

Splashscreen