人人都会AI编程

8.3 事件系统

更新时间:2026-07-11

1. 事件的工作方式

  • 任意一端主动发送

Rust 可以调用 window.emit("event-name", payload) 向某个窗口发送事件,也可以使用 app_handle.emit("event-name", payload) 向所有窗口广播。前端则通过 @tauri-apps/api/event 中的 emit 函数主动发送事件到 Rust。

  • 任意一端监听

前端使用 listen("event-name", callback) 订阅事件,Rust 端则通过 app.listen("event-name", callback)window.listen("event-name", callback) 接收来自前端的推送。

  • 一对多广播

同一个事件名可以被多个监听器订阅,发送一次所有人都会收到,非常适合状态同步或通知推送。


2. 前端 API(TypeScript)

import { listen, emit } from '@tauri-apps/api/event';

// 监听来自 Rust 的事件
const unlisten = await listen('backend-status', (event) => {
  console.log('收到负载:', event.payload);
});

// 主动发送事件给 Rust
await emit('user-action', { id: 1, type: 'click' });

// 取消监听(防止内存泄漏)
unlisten();

3. Rust 端 API

use tauri::Manager;

// 在命令中发送事件给当前窗口
#[tauri::command]
fn trigger_event(window: tauri::Window) {
    window.emit("backend-status", "准备就绪").unwrap();
}

// 在 setup 中监听前端事件
fn main() {
    tauri::Builder::default()
        .setup(|app| {
            let handle = app.handle();
            app.listen("user-action", |event| {
                println!("收到前端事件: {:?}", event.payload());
            });
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![trigger_event])
        .run(tauri::generate_context!())
        .expect("启动失败");
}

4. 使用场景

  • 后端状态推送:比如长时间运行的任务进度更新、WebSocket 消息转发,Rust 主动通知前端刷新界面。
  • 多窗口同步:在主窗口触发操作,通过事件广播通知其他窗口同步数据。
  • 前端主动通知后端:比如快捷键触发、页面生命周期事件,前端无需等待后端响应,直接 emit 即可。
  • 去耦合的模块通信:不同功能模块通过事件通信,不必直接互相依赖。

5. 注意事项

  • 载荷必须可序列化:事件携带的数据需要实现 Serde 的 Serialize / Deserialize,只支持 JSON 兼容的类型。
  • 事件名是字符串:建议用短横线命名(如 user-login),避免命名冲突。
  • 及时取消监听:长时间存在的监听(尤其是全局监听)在组件卸载或窗口关闭时应调用返回的 unlisten 函数,防止后台持续回调造成意外行为。
  • 不是响应-回复模式:如果你需要“发一个问题然后等答案”,应使用命令模式;事件更适合单向通知。

一句话概括:事件模式是 Tauri 的“神经网”,让 Rust 和前端可以自由地双向推送消息,解耦逻辑的同时保持界面实时响应,是构建实时交互应用不可或缺的机制。