useTauriEvent
Le composable useTauriEvent fournit une interface réactive pour écouter et émettre des événements Tauri, permettant une communication en temps réel entre votre backend Rust et votre frontend Vue.
Signature
typescript
function useTauriEvent<T = unknown>(eventName: string): TauriEventReturn<T>;Paramètres
eventName
- Type :
string - Requis : Oui
- Description : Le nom de l'événement Tauri à écouter
Valeur de Retour
Le composable retourne un objet avec les propriétés suivantes :
data
- Type :
Readonly<Ref<T | null>> - Description : Référence réactive contenant le dernier payload d'événement reçu
error
- Type :
Readonly<Ref<Error | null>> - Description : Référence réactive contenant toute erreur survenue
startListening
- Type :
() => Promise<void> - Description : Fonction pour commencer à écouter les événements
stopListening
- Type :
() => void - Description : Fonction pour arrêter d'écouter les événements
emit
- Type :
(payload: T) => Promise<void> - Description : Fonction pour émettre un événement avec le payload donné
Exemples d'Usage
Écoute d'Événements de Base
vue
<template>
<div>
<h3>Écouteur d'Événements</h3>
<div>
<button @click="startListening">Commencer l'écoute</button>
<button @click="stopListening">Arrêter l'écoute</button>
</div>
<div v-if="error" class="error">Erreur : {{ error.message }}</div>
<div v-if="data">
<h4>Dernier Événement Reçu :</h4>
<pre>{{ JSON.stringify(data, null, 2) }}</pre>
</div>
</div>
</template>
<script setup>
const { data, error, startListening, stopListening } =
useTauriEvent("my-event");
</script>Émission d'Événements
vue
<template>
<div>
<h3>Envoyer des Événements</h3>
<input v-model="message" placeholder="Entrez un message" />
<button @click="sendMessage" :disabled="!message">
Envoyer l'événement
</button>
<div v-if="error" class="error">Erreur : {{ error.message }}</div>
</div>
</template>
<script setup>
const message = ref("");
const { emit, error } = useTauriEvent("user-message");
const sendMessage = async () => {
if (message.value.trim()) {
await emit({
message: message.value,
timestamp: Date.now(),
});
message.value = "";
}
};
</script>Événements Typés avec TypeScript
vue
<template>
<div>
<h3>Application de Chat</h3>
<div class="chat-controls">
<button @click="startListening">Se connecter</button>
<button @click="stopListening">Se déconnecter</button>
</div>
<div class="chat-messages">
<div v-for="msg in messages" :key="msg.id" class="message">
<strong>{{ msg.user }} :</strong> {{ msg.text }}
<small>{{
new Date(msg.timestamp).toLocaleTimeString()
}}</small>
</div>
</div>
<div class="chat-input">
<input
v-model="newMessage"
@keyup.enter="sendMessage"
placeholder="Tapez un message..."
/>
<button @click="sendMessage">Envoyer</button>
</div>
</div>
</template>
<script setup>
interface ChatMessage {
id: string
user: string
text: string
timestamp: number
}
const messages = ref<ChatMessage[]>([])
const newMessage = ref('')
const {
data: receivedMessage,
error,
startListening,
stopListening,
emit
} = useTauriEvent<ChatMessage>('chat-message')
// Observer les nouveaux messages
watch(receivedMessage, (message) => {
if (message) {
messages.value.push(message)
}
})
const sendMessage = async () => {
if (newMessage.value.trim()) {
const message: ChatMessage = {
id: Date.now().toString(),
user: 'Vous',
text: newMessage.value,
timestamp: Date.now()
}
await emit(message)
newMessage.value = ''
}
}
// Auto-connexion au montage du composant
onMounted(() => {
startListening()
})
</script>Surveillance du Système de Fichiers
vue
<template>
<div>
<h3>Surveillance du Système de Fichiers</h3>
<div>
<button @click="startWatching">Commencer la surveillance</button>
<button @click="stopWatching">Arrêter la surveillance</button>
</div>
<div v-if="error" class="error">Erreur : {{ error.message }}</div>
<div v-if="fileEvent">
<h4>Événement du Système de Fichiers :</h4>
<p><strong>Action :</strong> {{ fileEvent.action }}</p>
<p><strong>Fichier :</strong> {{ fileEvent.path }}</p>
<p>
<strong>Heure :</strong>
{{ new Date(fileEvent.timestamp).toLocaleString() }}
</p>
</div>
<div class="recent-events">
<h4>Événements Récents :</h4>
<ul>
<li v-for="event in recentEvents" :key="event.timestamp">
{{ event.action }} - {{ event.path }}
</li>
</ul>
</div>
</div>
</template>
<script setup>
interface FileSystemEvent {
action: 'created' | 'modified' | 'deleted'
path: string
timestamp: number
}
const recentEvents = ref<FileSystemEvent[]>([])
const {
data: fileEvent,
error,
startListening: startWatching,
stopListening: stopWatching
} = useTauriEvent<FileSystemEvent>('file-system-event')
// Suivre les événements récents
watch(fileEvent, (event) => {
if (event) {
recentEvents.value.unshift(event)
// Garder seulement les 10 derniers événements
if (recentEvents.value.length > 10) {
recentEvents.value = recentEvents.value.slice(0, 10)
}
}
})
</script>Suivi de Progression
vue
<template>
<div>
<h3>Progression du Téléchargement</h3>
<button @click="startDownload" :disabled="isDownloading">
Commencer le téléchargement
</button>
<div v-if="isDownloading" class="progress-container">
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: `${progress?.percentage || 0}%` }"
></div>
</div>
<p>{{ progress?.percentage || 0 }}% - {{ progress?.status }}</p>
<p v-if="progress?.bytesDownloaded">
{{ formatBytes(progress.bytesDownloaded) }} /
{{ formatBytes(progress.totalBytes) }}
</p>
</div>
<div v-if="error" class="error">
Échec du téléchargement : {{ error.message }}
</div>
</div>
</template>
<script setup>
interface DownloadProgress {
percentage: number
status: string
bytesDownloaded: number
totalBytes: number
finished: boolean
}
const isDownloading = ref(false)
const {
data: progress,
error,
startListening,
stopListening,
emit
} = useTauriEvent<DownloadProgress>('download-progress')
const startDownload = async () => {
isDownloading.value = true
await startListening()
// Émettre la commande de début de téléchargement
await emit({ action: 'start', url: 'https://example.com/file.zip' })
}
// Observer la fin du téléchargement
watch(progress, (prog) => {
if (prog?.finished) {
isDownloading.value = false
stopListening()
}
})
const formatBytes = (bytes: number) => {
return (bytes / 1024 / 1024).toFixed(2) + ' MB'
}
</script>
<style scoped>
.progress-container {
margin: 1rem 0;
}
.progress-bar {
width: 100%;
height: 20px;
background-color: #f0f0f0;
border-radius: 10px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #4caf50;
transition: width 0.3s ease;
}
</style>Gestion du Cycle de Vie
Le composable gère automatiquement le nettoyage :
vue
<script setup>
const { startListening, stopListening } = useTauriEvent("my-event");
// Commencer l'écoute au montage du composant
onMounted(() => {
startListening();
});
// Le nettoyage est automatique au démontage du composant
// Pas besoin d'appeler manuellement stopListening dans onUnmounted
</script>Gestion d'Erreurs
Gérer différents types d'erreurs :
vue
<script setup>
const { error, startListening } = useTauriEvent("my-event");
watchEffect(() => {
if (error.value) {
if (error.value.message.includes("Tauri API not available")) {
console.log(
"Fonctionnement en mode navigateur - événements désactivés"
);
} else {
console.error("Erreur d'événement:", error.value);
// Peut-être afficher une notification utilisateur
}
}
});
</script>Bonnes Pratiques
1. Utiliser TypeScript pour les Payloads d'Événements
Définir des interfaces pour vos données d'événement :
typescript
interface UserAction {
type: "login" | "logout" | "register";
userId: string;
timestamp: number;
}
const { data, emit } = useTauriEvent<UserAction>("user-action");2. Gérer les États de Connexion
Fournir un retour sur l'état d'écoute :
vue
<template>
<div>
<span class="status" :class="{ listening: isListening }">
{{ isListening ? "Connecté" : "Déconnecté" }}
</span>
</div>
</template>
<script setup>
const isListening = ref(false);
const { startListening, stopListening } = useTauriEvent("status");
const connect = async () => {
await startListening();
isListening.value = true;
};
const disconnect = () => {
stopListening();
isListening.value = false;
};
</script>3. Débouncer les Événements Rapides
Pour les événements haute fréquence, considérez le debouncing :
vue
<script setup>
import { debounce } from "lodash-es";
const { data } = useTauriEvent("mouse-position");
const debouncedHandler = debounce((position) => {
// Gérer la mise à jour de position
console.log("Position de la souris:", position);
}, 100);
watch(data, debouncedHandler);
</script>4. Valider les Données d'Événement
Toujours valider les données d'événement entrantes :
vue
<script setup>
const { data } = useTauriEvent("user-data");
watch(data, (userData) => {
if (userData && typeof userData === "object" && "id" in userData) {
// Les données sont valides
handleUserData(userData);
} else {
console.warn("Données utilisateur invalides reçues:", userData);
}
});
</script>Intégration Backend Rust
Émettre des Événements depuis Rust
rust
use tauri::{AppHandle, Manager};
#[tauri::command]
fn process_data(app: AppHandle) -> Result<(), String> {
// Faire du traitement...
// Émettre un événement vers le frontend
app.emit_all("data-processed", ProcessedData {
id: 123,
result: "Succès".to_string(),
timestamp: chrono::Utc::now().timestamp(),
}).map_err(|e| e.to_string())?;
Ok(())
}Écouter les Événements en Rust
rust
use tauri::{Manager, Window};
fn setup_event_listeners(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
let window = app.get_window("main").unwrap();
window.listen("user-action", |event| {
println!("Action utilisateur reçue: {:?}", event.payload());
// Gérer l'événement
});
Ok(())
}Articles Liés
- useTauriInvoke - Pour exécuter des commandes Tauri
- Exemples - Voir plus d'exemples d'usage