命令系统 #
一、命令基础 #
1.1 什么是命令 #
命令是 Tauri 中前后端通信的核心机制。前端通过 invoke() 调用后端定义的 Rust 函数。
text
┌─────────────┐ invoke() ┌─────────────┐
│ 前端 │ ───────────────► │ 后端 │
│ JavaScript │ │ Rust │
│ │ ◄─────────────── │ Command │
│ │ Result │ │
└─────────────┘ └─────────────┘
1.2 定义命令 #
rust
// 使用 #[tauri::command] 宏定义命令
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
// 注册命令
.invoke_handler(tauri::generate_handler![greet])
1.3 调用命令 #
typescript
import { invoke } from '@tauri-apps/api/core';
const result = await invoke<string>('greet', { name: 'World' });
console.log(result); // "Hello, World!"
二、参数传递 #
2.1 基本类型 #
rust
#[tauri::command]
fn basic_types(
string_param: String,
int_param: i32,
float_param: f64,
bool_param: bool,
) -> String {
format!("string: {}, int: {}, float: {}, bool: {}",
string_param, int_param, float_param, bool_param)
}
typescript
await invoke('basic_types', {
stringParam: 'hello',
intParam: 42,
floatParam: 3.14,
boolParam: true
});
2.2 可选参数 #
rust
#[tauri::command]
fn optional_param(name: Option<String>) -> String {
match name {
Some(n) => format!("Hello, {}!", n),
None => "Hello, stranger!".to_string(),
}
}
typescript
// 传递参数
await invoke('optional_param', { name: 'World' }); // "Hello, World!"
// 不传递参数
await invoke('optional_param', {}); // "Hello, stranger!"
2.3 结构体参数 #
rust
use serde::Deserialize;
#[derive(Deserialize)]
struct User {
name: String,
age: u32,
email: String,
}
#[tauri::command]
fn create_user(user: User) -> String {
format!("Created user: {} ({} years old)", user.name, user.age)
}
typescript
await invoke('create_user', {
user: {
name: 'Alice',
age: 25,
email: 'alice@example.com'
}
});
2.4 集合类型 #
rust
#[tauri::command]
fn process_list(items: Vec<String>) -> usize {
items.len()
}
#[tauri::command]
fn process_map(data: std::collections::HashMap<String, i32>) -> i32 {
data.values().sum()
}
typescript
// 列表
await invoke('process_list', { items: ['a', 'b', 'c'] });
// Map
await invoke('process_map', { data: { a: 1, b: 2, c: 3 } });
三、返回值处理 #
3.1 基本返回类型 #
rust
#[tauri::command]
fn return_string() -> String {
"Hello".to_string()
}
#[tauri::command]
fn return_number() -> i32 {
42
}
#[tauri::command]
fn return_bool() -> bool {
true
}
#[tauri::command]
fn return_option() -> Option<String> {
Some("value".to_string())
}
3.2 结构体返回 #
rust
use serde::Serialize;
#[derive(Serialize)]
struct UserInfo {
id: u32,
name: String,
active: bool,
}
#[tauri::command]
fn get_user() -> UserInfo {
UserInfo {
id: 1,
name: "Alice".to_string(),
active: true,
}
}
typescript
interface UserInfo {
id: number;
name: string;
active: boolean;
}
const user = await invoke<UserInfo>('get_user');
console.log(user.name); // "Alice"
3.3 集合返回 #
rust
#[tauri::command]
fn get_users() -> Vec<UserInfo> {
vec![
UserInfo { id: 1, name: "Alice".to_string(), active: true },
UserInfo { id: 2, name: "Bob".to_string(), active: false },
]
}
#[tauri::command]
fn get_config() -> std::collections::HashMap<String, String> {
let mut config = std::collections::HashMap::new();
config.insert("theme".to_string(), "dark".to_string());
config.insert("lang".to_string(), "en".to_string());
config
}
四、错误处理 #
4.1 Result 类型 #
rust
#[tauri::command]
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
typescript
try {
const result = await invoke<number>('divide', { a: 10, b: 2 });
console.log(result); // 5
} catch (error) {
console.error(error); // "Division by zero"
}
4.2 自定义错误类型 #
rust
use serde::Serialize;
#[derive(Debug, Serialize)]
struct AppError {
code: String,
message: String,
}
impl From<std::io::Error> for AppError {
fn from(error: std::io::Error) -> Self {
AppError {
code: "IO_ERROR".to_string(),
message: error.to_string(),
}
}
}
#[tauri::command]
fn read_config() -> Result<String, AppError> {
std::fs::read_to_string("config.json")?;
Ok("success".to_string())
}
4.3 使用 anyhow #
rust
use anyhow::Result;
#[tauri::command]
fn complex_operation() -> Result<String> {
// 使用 ? 操作符自动转换错误
let content = std::fs::read_to_string("file.txt")?;
Ok(content)
}
五、异步命令 #
5.1 异步函数 #
rust
#[tauri::command]
async fn async_greet(name: String) -> String {
// 模拟异步操作
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
format!("Hello, {}!", name)
}
5.2 异步文件操作 #
rust
#[tauri::command]
async fn read_file_async(path: String) -> Result<String, String> {
tokio::fs::read_to_string(&path)
.await
.map_err(|e| e.to_string())
}
5.3 异步 HTTP 请求 #
rust
#[tauri::command]
async fn fetch_data(url: String) -> Result<String, String> {
let response = reqwest::get(&url)
.await
.map_err(|e| e.to_string())?;
let body = response.text()
.await
.map_err(|e| e.to_string())?;
Ok(body)
}
六、状态管理 #
6.1 共享状态 #
rust
use std::sync::Mutex;
struct AppState {
counter: Mutex<i32>,
}
#[tauri::command]
fn increment(state: tauri::State<AppState>) -> i32 {
let mut counter = state.counter.lock().unwrap();
*counter += 1;
*counter
}
#[tauri::command]
fn get_counter(state: tauri::State<AppState>) -> i32 {
*state.counter.lock().unwrap()
}
// 注册状态
tauri::Builder::default()
.manage(AppState {
counter: Mutex::new(0),
})
.invoke_handler(tauri::generate_handler![increment, get_counter])
.run(tauri::generate_context!())
.expect("error while running tauri application");
6.2 多状态管理 #
rust
struct Database {
connection: Mutex<String>,
}
struct Cache {
data: Mutex<std::collections::HashMap<String, String>>,
}
#[tauri::command]
fn use_multiple_states(
db: tauri::State<Database>,
cache: tauri::State<Cache>,
) -> String {
// 使用多个状态
"ok".to_string()
}
// 注册多个状态
tauri::Builder::default()
.manage(Database { connection: Mutex::new("connection".to_string()) })
.manage(Cache { data: Mutex::new(std::collections::HashMap::new()) })
.invoke_handler(tauri::generate_handler![use_multiple_states])
.run(tauri::generate_context!())
.expect("error while running tauri application");
七、窗口访问 #
7.1 获取窗口 #
rust
#[tauri::command]
async fn close_window(window: tauri::Window) {
window.close().await.unwrap();
}
#[tauri::command]
async fn set_title(window: tauri::Window, title: String) {
window.set_title(&title).await.unwrap();
}
7.2 获取应用句柄 #
rust
#[tauri::command]
fn get_app_info(app: tauri::AppHandle) -> String {
format!("{} - {}",
app.config().product_name.clone().unwrap_or_default(),
app.config().version.clone().unwrap_or_default()
)
}
八、命令注册 #
8.1 基本注册 #
rust
.invoke_handler(tauri::generate_handler![
greet,
increment,
get_counter,
])
8.2 模块化注册 #
rust
mod commands {
pub mod file {
#[tauri::command]
pub fn read() -> String { "read".to_string() }
#[tauri::command]
pub fn write() -> String { "write".to_string() }
}
pub mod system {
#[tauri::command]
pub fn info() -> String { "info".to_string() }
}
}
.invoke_handler(tauri::generate_handler![
commands::file::read,
commands::file::write,
commands::system::info,
])
九、TypeScript 类型 #
9.1 类型定义 #
typescript
// types/commands.ts
export interface User {
id: number;
name: string;
email: string;
}
export interface AppError {
code: string;
message: string;
}
export interface Commands {
greet: (name: string) => Promise<string>;
getUser: () => Promise<User>;
create_user: (user: User) => Promise<void>;
}
9.2 类型安全调用 #
typescript
// utils/tauri.ts
import { invoke } from '@tauri-apps/api/core';
export async function invokeTyped<T>(cmd: string, args?: Record<string, unknown>): Promise<T> {
return invoke<T>(cmd, args);
}
// 使用
const user = await invokeTyped<User>('get_user');
十、最佳实践 #
10.1 命令命名 #
rust
// 推荐:动词开头,清晰描述功能
#[tauri::command]
fn get_user() -> User { /* ... */ }
#[tauri::command]
fn create_user() -> User { /* ... */ }
#[tauri::command]
fn delete_user() -> bool { /* ... */ }
// 不推荐:模糊命名
#[tauri::command]
fn user() -> User { /* ... */ }
10.2 参数验证 #
rust
#[tauri::command]
fn create_user(name: String, email: String) -> Result<User, String> {
if name.is_empty() {
return Err("Name cannot be empty".to_string());
}
if !email.contains('@') {
return Err("Invalid email format".to_string());
}
Ok(User { name, email })
}
10.3 批量操作 #
rust
// 不推荐:多次调用
#[tauri::command]
fn get_user(id: u32) -> User { /* ... */ }
// 推荐:批量获取
#[tauri::command]
fn get_users(ids: Vec<u32>) -> Vec<User> { /* ... */ }
十一、调试技巧 #
11.1 日志输出 #
rust
#[tauri::command]
fn debug_command(param: String) -> String {
println!("Received param: {}", param);
format!("Processed: {}", param)
}
11.2 错误追踪 #
rust
#[tauri::command]
fn tracked_operation() -> Result<String, String> {
std::fs::read_to_string("file.txt")
.map_err(|e| {
eprintln!("Error reading file: {}", e);
format!("Failed to read file: {}", e)
})
}
十二、总结 #
12.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 命令定义 | 使用 #[tauri::command] 宏 |
| 参数传递 | 支持基本类型、结构体、集合 |
| 返回值 | 支持同步和异步返回 |
| 错误处理 | 使用 Result 类型 |
| 状态管理 | 通过 tauri::State 共享 |
12.2 下一步 #
现在你已经掌握了 Tauri 的命令系统,接下来让我们学习 状态管理,了解如何在应用中管理共享状态!
最后更新:2026-03-28