“如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》
“有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》
“维持现状意味着空耗你的努力和生命。”——纪伯伦
第一节 自定义启动画面
一. 概述
在CS端大多数项目启动都会有一个代表性的启动界面,者本章节中我们将了解如何在Tauri项目中自定义自动界面。
本章节开始逐步涉及一些代码编程,本章节开始,章节射击的编码会统一放到我的GitCode上,可以结合使用,提升下学习效率。
二 . 创建启动画面
第一步 创建项目
这一步骤参见:第四章 第一节 项目创建及结构说明
第二步 在Tauri.conf.json 中注册窗口
在理我们的配置如下:
····
"app": {
"windows": [
{
"label": "main",
"visible": false
},
{
"label": "start",
"url": "/start"
}
],
"security": {
"csp": null
}
},
····
第三步 创建启动页面
启动页面的创建和我闷平时开发的页面没有区别,你可以借助vue或者react技术创建一个页面,这里我为了便捷创建一个html的页面,用于演示,实际开发中我也建议大家创建一个html页面,毕竟启动页面不是为了公告就是为了宣传。
start.html ,页面放置到项目根目录下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>启动页面</title>
<style>
body,
html {
margin: 0;
padding: 0;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: #f7f7f7;
}
.splash {
text-align: center;
font-family: "Arial", sans-serif;
color: #333;
}
.splash h1 {
font-size: 3em;
margin-bottom: 0.5em;
}
.splash p {
font-size: 1.2em;
}
</style>
</head>
<body>
<div class="splash">
<h1>欢迎来到我的网站</h1>
<p>正在载入...</p>
</div>
<script>
// 假设你有一个函数来检查加载状态
function checkLoading() {
// 假设当所有资源加载完毕后会设置一个特定的cookie或localStorage
if (localStorage.getItem("loaded") === "true") {
// 跳转到主页
window.location.href = "index.html";
} else {
// 继续显示启动屏幕
setTimeout(checkLoading, 100); // 每隔一段时间检查一次
}
}
checkLoading();
</script>
</body>
</html>
效果如下:
第四步 配置页面
在理涉及到前后端的配置
-
前端配置
在src下创建start.ts,代码如下:
import { invoke } from "@tauri-apps/api/core"; 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" }); } export default () => { // Effectively a JavaScript main function window.addEventListener("DOMContentLoaded", () => { setup(); }); };
在main.ts 中引入
import { createApp } from "vue"; import App from "./App.vue"; import start from "./start"; createApp(App).mount("#app"); start();
-
后端配置
-
安装依赖 tokio
cd src-tauri cargo add tokio
安装成功后会在cargo.toml 文件中,出现 tokio 的依赖配制
-
在 src-tauri 的src 目录下 创建 tokio .rs 文件
// Import functionalities we'll be using use std::sync::Mutex; use tauri::{AppHandle, Manager, State}; use tokio::time::{sleep, Duration}; // Create a struct we'll use to track the completion of // setup related tasks pub struct SetupState { pub(crate) frontend_task: bool, pub(crate) backend_task: bool, } // A custom task for setting the state of a setup task #[tauri::command] pub 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("start").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 pub 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(()) }
-
在lib.rs 中引入
mod tokio; use std::sync::Mutex; use tauri::async_runtime::spawn; use tokio::{set_complete,setup,SetupState}; // 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_opener::init()) // .invoke_handler(tauri::generate_handler![greet]) // .run(tauri::generate_context!()) // .expect("error while running tauri application"); // } // 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"); }
-
第五步 运行应用程序
现在您应该会看到一个启动画面窗口弹出,前端和后端都将执行各自 3 秒设置任务,之后启动画面消失并显示主窗口!
停留3秒后
遇到的问题及解决办法
-
在启动项目时,控制台出现以下错误:
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
解决办法:rust编译器提示你进行错误“回溯”:
在window 下:Powershell
$env:RUST_BACKTRACE=1 ; cargo run
window cmd下:
set RUST_BACKTRACE=1
在linux与macos 下
RUST_BACKTRACE=1 cargo run