在现代桌面应用开发中,Tauri 框架凭借其轻量级、高性能和安全性,成为开发者们构建跨平台应用的首选工具之一。Tauri 允许开发者使用现代前端框架(如 React、Vue 或 Svelte)构建用户界面,同时利用 Rust 语言处理高效且安全的后端逻辑。然而,前后端之间的高效通信是构建功能丰富且稳定的 Tauri 应用的关键。本文将详细介绍 Tauri 中前后端通信的主要方式——Commands(命令)、Events(事件) 及 Channels(通道),并通过示例代码帮助您更好地理解和应用这些技术。
目录
Tauri 简介
Tauri 是一个用于构建跨平台桌面应用的框架,支持 Windows、macOS 和 Linux。它利用前端技术(如 HTML、CSS、JavaScript)构建用户界面,并使用 Rust 处理后端逻辑。与 Electron 相比,Tauri 生成的应用体积更小,性能更优,且具备更高的安全性。
前后端通信方式概述
在 Tauri 框架中,前端(通常使用 JavaScript 框架如 React、Vue 或 Svelte)与后端(Rust 编写)之间的通信是实现应用功能的核心。Tauri 提供了多种通信机制,主要包括 Commands(命令)、Events(事件) 和 Channels(通道)。除此之外,还有一些其他的通信方式,如在 Rust 中执行 JavaScript 代码。以下将详细介绍这些通信方式、它们的区别及适用场景。
Commands(命令)
Commands 是前端调用后端 Rust 函数的主要方式。通过命令,前端可以请求后端执行特定任务并获取结果。这种通信方式类似于前端发起的远程过程调用(RPC)。
使用场景
- 执行复杂逻辑��需要后端处理的数据计算、文件操作、数据库交互等。
- 获取后端数据:例如,从数据库获取数据并在前端展示。
- 安全性需求:通过命令调用,能够在 Tauri 的安全模型下细粒度地控制权限。
实现步骤
-
在 Rust 后端定义命令
使用
#[tauri::command]
宏定义一个可供前端调用的函数。src-tauri/src/lib.rs#[tauri::command]
fn my_custom_command() {
println!("我被 JavaScript 调用了!");
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![my_custom_command])
.run(tauri::generate_context!())
.expect("运行 Tauri 应用时出错");
}:::note命令名称必须唯一。:::
:::note由于胶水代码生成的限制,在
lib.rs
文件中定义的命令不能标记为pub
。如果将其标记为公共函数,您将看到如下错误:error[E0255]: the name `__cmd__command_name` is defined multiple times
--> src/lib.rs:28:8
|
27 | #[tauri::command]
| ----------------- previous definition of the macro `__cmd__command_name` here
28 | pub fn x() {}
| ^ `__cmd__command_name` reimported here
|
= note: `__cmd__command_name` must be defined only once in the macro namespace of this module:::
-
在前端调用命令
使用
@tauri-apps/api
提供的invoke
方法调用后端命令。前端 JavaScript 代码示例(如 React 组件)import { invoke } from '@tauri-apps/api/core';
async function greetUser() {
try {
const greeting = await invoke('my_custom_command');
console.log(greeting); // 输出: "我被 JavaScript 调用了!"
} catch (error) {
console.error('调用命令时出错:', error);
}
}
// 在适当的生命周期钩子中调用 greetUser -
配置权限
在
tauri.conf.json
中,通过 Capabilities 和 Permissions 配置命令的访问权限,确保命令的安全调用。tauri.conf.json 示例{
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/cli/schema.json",
"package": {
"productName": "Pomodoro Timer",
"version": "0.1.0"
},
"tauri": {
"windows": [
{
"label": "main",
"title": "ToDo Pomodoro",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false,
"decorations": true,
"transparent": false,
"alwaysOnTop": false,
"visible": true,
"url": "http://localhost:3000",
"webviewAttributes": {
"webPreferences": {
"nodeIntegration": false
}
}
}
],
"security": {
"capabilities": [
{
"identifier": "greet-capability",
"description": "Allows the main window to greet users.",
"windows": ["main"],
"permissions": ["core:default"]
}
]
},
"bundle": {
"active": true,
"targets": "all",
"identifier": "com.yuxuetr.pomodoro",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
}
}
}
Events(事件)
Events 是 Tauri 中实现后端向前端推送消息的机制。与 Commands 不同,Events 是单向的,适用于需要实时通知前端的场景。
使用场景
- 状态更新通知:后端状态变化时通知前端
- 长时间任务进度:报告后台任务的执行进度
- 系统事件通知:如系统状态变化、文件变动等
实现步骤
-
在 Rust 后端发送事件
src-tauri/src/lib.rsuse tauri::Manager;
#[tauri::command]
async fn start_process(window: tauri::Window) {
// 模拟一个耗时操作
for i in 0..100 {
window.emit("process-progress", i).unwrap();
std::thread::sleep(std::time::Duration::from_millis(100));
}
} -
在前端监听事件
import { listen } from '@tauri-apps/api/event';
// 监听进度事件
await listen('process-progress', (event) => {
console.log('Progress:', event.payload);
});
Channels(通道)
Channels 提供了一种双向的、持久的通信通道,特别适合需要持续数据交换的场景。