<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>http://mochiuwiki.e2.valueserver.jp/index.php?action=history&amp;feed=atom&amp;title=Tauri%E3%81%AE%E5%9F%BA%E7%A4%8E_-_%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E9%80%81%E5%8F%97%E4%BF%A1</id>
	<title>Tauriの基礎 - イベントの送受信 - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="http://mochiuwiki.e2.valueserver.jp/index.php?action=history&amp;feed=atom&amp;title=Tauri%E3%81%AE%E5%9F%BA%E7%A4%8E_-_%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E9%80%81%E5%8F%97%E4%BF%A1"/>
	<link rel="alternate" type="text/html" href="http://mochiuwiki.e2.valueserver.jp/index.php?title=Tauri%E3%81%AE%E5%9F%BA%E7%A4%8E_-_%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E9%80%81%E5%8F%97%E4%BF%A1&amp;action=history"/>
	<updated>2026-09-02T11:42:42Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://mochiuwiki.e2.valueserver.jp/index.php?title=Tauri%E3%81%AE%E5%9F%BA%E7%A4%8E_-_%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E9%80%81%E5%8F%97%E4%BF%A1&amp;diff=14520&amp;oldid=prev</id>
		<title>Wiki: ページの作成:「== 概要 == Tauriのイベントシステムは、RustバックエンドとWebフロントエンド間の双方向通信を実現する軽量なメカニズムである。&lt;br&gt; Commandsとは異なり、イベントは戻り値を必要としない通知型の通信に適しており、バックエンドからフロントエンドへのプッシュ通知や、コンポーネント間の状態共有に活用される。&lt;br&gt; &lt;br&gt; 下表に、イベントシステム…」</title>
		<link rel="alternate" type="text/html" href="http://mochiuwiki.e2.valueserver.jp/index.php?title=Tauri%E3%81%AE%E5%9F%BA%E7%A4%8E_-_%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E9%80%81%E5%8F%97%E4%BF%A1&amp;diff=14520&amp;oldid=prev"/>
		<updated>2026-03-04T06:57:54Z</updated>

		<summary type="html">&lt;p&gt;ページの作成:「== 概要 == Tauriのイベントシステムは、RustバックエンドとWebフロントエンド間の双方向通信を実現する軽量なメカニズムである。&amp;lt;br&amp;gt; Commandsとは異なり、イベントは戻り値を必要としない通知型の通信に適しており、バックエンドからフロントエンドへのプッシュ通知や、コンポーネント間の状態共有に活用される。&amp;lt;br&amp;gt; &amp;lt;br&amp;gt; 下表に、イベントシステム…」&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 概要 ==&lt;br /&gt;
Tauriのイベントシステムは、RustバックエンドとWebフロントエンド間の双方向通信を実現する軽量なメカニズムである。&amp;lt;br&amp;gt;&lt;br /&gt;
Commandsとは異なり、イベントは戻り値を必要としない通知型の通信に適しており、バックエンドからフロントエンドへのプッシュ通知や、コンポーネント間の状態共有に活用される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
下表に、イベントシステムの主な特徴を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Tauriイベントシステムの特徴&lt;br /&gt;
! 特徴 !! 説明&lt;br /&gt;
|-&lt;br /&gt;
| 非同期通信 || 送信側は受信側の応答を待たずに処理を継続できる。&amp;lt;br&amp;gt;一方向の通知として動作し、fire-and-forgetパターンに適している。&lt;br /&gt;
|-&lt;br /&gt;
| 軽量 || JSONベースのシリアライゼーションにより、オーバーヘッドが小さい。&amp;lt;br&amp;gt;高頻度なイベント送信にも対応できる。&lt;br /&gt;
|-&lt;br /&gt;
| 柔軟なターゲティング || 全リスナーへのブロードキャスト、特定WebViewへのユニキャスト、フィルタリング送信が可能である。&amp;lt;br&amp;gt;アプリケーションの要件に応じた送信先制御ができる。&lt;br /&gt;
|-&lt;br /&gt;
| 型安全性 || Rustの &amp;lt;code&amp;gt;Serialize&amp;lt;/code&amp;gt; トレイトとTypeScriptの型定義により、型安全な通信が実現できる。&amp;lt;br&amp;gt;コンパイル時の型チェックでランタイムエラーを防止できる。&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
イベントはフロントエンド (JavaScript / TypeScript) からRustバックエンドへの送信、およびRustバックエンドからフロントエンドへの送信の両方向で利用できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== イベントシステムの基本 ==&lt;br /&gt;
==== Commandsとの違い ====&lt;br /&gt;
Tauriには、フロントエンドとバックエンド間の通信手段として、&amp;lt;u&amp;gt;Commands&amp;lt;/u&amp;gt; と &amp;lt;u&amp;gt;Events&amp;lt;/u&amp;gt; の2つが存在する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
下表に、それぞれの特徴を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ CommandsとEventsの比較&lt;br /&gt;
! 特徴 !! Commands !! Events&lt;br /&gt;
|-&lt;br /&gt;
| 通信パターン || リクエスト・レスポンス型 || 通知型 (fire-and-forget)&lt;br /&gt;
|-&lt;br /&gt;
| 戻り値 || あり (Promiseで受信) || なし&lt;br /&gt;
|-&lt;br /&gt;
| 主な用途 || データの取得、処理の実行 || 状態通知、プログレス更新、イベント通知&lt;br /&gt;
|-&lt;br /&gt;
| 送信方向 || フロントエンド → バックエンド || 双方向&lt;br /&gt;
|-&lt;br /&gt;
| 待機 || 呼び出し側は完了を待機 || 送信側は応答を待たない&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 使用シーンの例 ====&lt;br /&gt;
イベントシステムが適しているシーンを以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* ダウンロード進捗の通知&lt;br /&gt;
*: バックエンドでダウンロードが進行するたびに、進捗率をフロントエンドに通知する。&lt;br /&gt;
* ファイル変更の監視&lt;br /&gt;
*: ファイルシステムの変更を検知し、フロントエンドに変更内容を通知する。&lt;br /&gt;
* ログイン状態の同期&lt;br /&gt;
*: 認証完了時にセッショントークンを全WebViewに通知する。&lt;br /&gt;
* バックグラウンド処理の完了通知&lt;br /&gt;
*: 長時間の処理が完了したタイミングでユーザーに通知する。&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== emit : イベントの送信 ==&lt;br /&gt;
==== Rustからの送信 ====&lt;br /&gt;
Rustバックエンドからイベントを送信するには、&amp;lt;code&amp;gt;AppHandle&amp;lt;/code&amp;gt; の &amp;lt;code&amp;gt;emit&amp;lt;/code&amp;gt; メソッドを使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;emit&amp;lt;/code&amp;gt; は全てのリスナーにイベントをブロードキャストする。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
基本的な使用例を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::{AppHandle, Emitter};&lt;br /&gt;
 &lt;br /&gt;
 #[tauri::command]&lt;br /&gt;
 fn start_download(app: AppHandle, url: String) {&lt;br /&gt;
    // イベント名とペイロードを指定して送信&lt;br /&gt;
    // emit()は全リスナーにブロードキャストする&lt;br /&gt;
    app.emit(&amp;quot;download-started&amp;quot;, &amp;amp;url).unwrap();&lt;br /&gt;
 &lt;br /&gt;
    // 進捗状況の通知&lt;br /&gt;
    for progress in [25, 50, 75, 100] {&lt;br /&gt;
       app.emit(&amp;quot;download-progress&amp;quot;, progress).unwrap();&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // 完了通知&lt;br /&gt;
    app.emit(&amp;quot;download-finished&amp;quot;, &amp;amp;url).unwrap();&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== フロントエンドからの送信 ====&lt;br /&gt;
フロントエンド (TypeScript / JavaScript) からイベントを送信するには、&amp;lt;code&amp;gt;@tauri-apps/api/event&amp;lt;/code&amp;gt; の &amp;lt;code&amp;gt;emit&amp;lt;/code&amp;gt; 関数を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { emit } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // グローバルイベントの送信&lt;br /&gt;
 // 第1引数: イベント名、第2引数: ペイロード&lt;br /&gt;
 emit(&amp;#039;file-selected&amp;#039;, &amp;#039;/path/to/file&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
 // オブジェクトをペイロードとして送信&lt;br /&gt;
 emit(&amp;#039;user-action&amp;#039;, {&lt;br /&gt;
   action: &amp;#039;click&amp;#039;,&lt;br /&gt;
   target: &amp;#039;submit-button&amp;#039;,&lt;br /&gt;
   timestamp: Date.now()&lt;br /&gt;
 });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== WebView固有のイベント送信 ====&lt;br /&gt;
現在のWebViewからイベントを送信するには、&amp;lt;code&amp;gt;getCurrentWebviewWindow&amp;lt;/code&amp;gt; を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { getCurrentWebviewWindow } from &amp;#039;@tauri-apps/api/webviewWindow&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 const appWebview = getCurrentWebviewWindow();&lt;br /&gt;
 &lt;br /&gt;
 // 現在のWebViewにイベントを送信&lt;br /&gt;
 appWebview.emit(&amp;#039;route-changed&amp;#039;, { url: window.location.href });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== listen : イベントの受信 ==&lt;br /&gt;
==== フロントエンドでの受信 ====&lt;br /&gt;
フロントエンドでイベントを受信するには、&amp;lt;code&amp;gt;listen&amp;lt;/code&amp;gt; 関数を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;listen&amp;lt;/code&amp;gt; はグローバルイベントをリッスンし、イベントが発生するたびにコールバック関数が実行される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
基本的な使用例を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { listen } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // イベントリスナーの登録&lt;br /&gt;
 // 戻り値は unlisten 関数 (後でリスナーを解除する時に使用)&lt;br /&gt;
 const unlisten = await listen&amp;lt;string&amp;gt;(&amp;#039;download-progress&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
   console.log(`ダウンロード進捗: ${event.payload}%`);&lt;br /&gt;
 });&lt;br /&gt;
 &lt;br /&gt;
 // 使用後にリスナーを解除する&lt;br /&gt;
 // unlisten();&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 型付きペイロードの受信 ====&lt;br /&gt;
&amp;lt;code&amp;gt;listen&amp;lt;/code&amp;gt; 関数はジェネリクスをサポートしており、ペイロードの型を指定できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { listen } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // ペイロードの型を定義&lt;br /&gt;
 interface DownloadStarted {&lt;br /&gt;
   url: string;&lt;br /&gt;
   downloadId: number;&lt;br /&gt;
   contentLength: number;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // 型を指定してリッスン&lt;br /&gt;
 const unlisten = await listen&amp;lt;DownloadStarted&amp;gt;(&amp;#039;download-started&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
   console.log(`ダウンロード開始: ${event.payload.contentLength} バイト`);&lt;br /&gt;
   console.log(`URL: ${event.payload.url}`);&lt;br /&gt;
   console.log(`ID: ${event.payload.downloadId}`);&lt;br /&gt;
 });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== WebView固有イベントの受信 ====&lt;br /&gt;
特定のWebView宛てのイベントを受信するには、&amp;lt;code&amp;gt;getCurrentWebviewWindow&amp;lt;/code&amp;gt; の &amp;lt;code&amp;gt;listen&amp;lt;/code&amp;gt; メソッドを使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { getCurrentWebviewWindow } from &amp;#039;@tauri-apps/api/webviewWindow&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 const appWebview = getCurrentWebviewWindow();&lt;br /&gt;
 &lt;br /&gt;
 // WebView固有のイベントをリッスン&lt;br /&gt;
 appWebview.listen&amp;lt;string&amp;gt;(&amp;#039;logged-in&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
   // ログイン時にセッショントークンを受け取る&lt;br /&gt;
   localStorage.setItem(&amp;#039;session-token&amp;#039;, event.payload);&lt;br /&gt;
 });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Rustでの受信 ====&lt;br /&gt;
Rustバックエンドでもイベントをリッスンできる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::Manager;&lt;br /&gt;
 &lt;br /&gt;
 fn setup_listeners(app: &amp;amp;tauri::AppHandle) {&lt;br /&gt;
    // イベントリスナーの登録&lt;br /&gt;
    app.listen(&amp;quot;frontend-event&amp;quot;, |event| {&lt;br /&gt;
       println!(&amp;quot;イベントを受信: {:?}&amp;quot;, event.payload());&lt;br /&gt;
    });&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== unlisten : リスナーの解除 ==&lt;br /&gt;
==== 解除の重要性 ====&lt;br /&gt;
イベントリスナーは、不要になった時点で必ず解除する必要がある。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
特にSPA (Single Page Application) では、ページ遷移してもリスナーが自動的に解除されないため、メモリリークの原因となる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== フロントエンドでの解除 ====&lt;br /&gt;
&amp;lt;code&amp;gt;listen&amp;lt;/code&amp;gt; 関数は &amp;lt;code&amp;gt;unlisten&amp;lt;/code&amp;gt; 関数を返す。&amp;lt;br&amp;gt;&lt;br /&gt;
この関数を呼び出すことでリスナーを解除できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { listen } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // リスナーの登録&lt;br /&gt;
 const unlisten = await listen(&amp;#039;my-event&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
   console.log(&amp;#039;イベントを受信:&amp;#039;, event.payload);&lt;br /&gt;
 });&lt;br /&gt;
 &lt;br /&gt;
 // リスナーの解除&lt;br /&gt;
 // これ以降、イベントを受信しなくなる&lt;br /&gt;
 unlisten();&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Rustでの解除 ====&lt;br /&gt;
Rustでは、&amp;lt;code&amp;gt;listen&amp;lt;/code&amp;gt; が返す &amp;lt;code&amp;gt;EventHandler&amp;lt;/code&amp;gt; を &amp;lt;code&amp;gt;unlisten&amp;lt;/code&amp;gt; に渡して解除する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::Manager;&lt;br /&gt;
 &lt;br /&gt;
 fn manage_listener(app: &amp;amp;tauri::AppHandle) {&lt;br /&gt;
    // リスナーの登録 (EventHandler を取得)&lt;br /&gt;
    let handler = app.listen(&amp;quot;status-changed&amp;quot;, |event| {&lt;br /&gt;
       println!(&amp;quot;ステータス変更: {:?}&amp;quot;, event.payload());&lt;br /&gt;
    });&lt;br /&gt;
 &lt;br /&gt;
    // リスナーの解除&lt;br /&gt;
    app.unlisten(handler);&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 条件付きでの解除 ====&lt;br /&gt;
イベントハンドラ内で条件に基づいてリスナーを解除することもできる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::Manager;&lt;br /&gt;
 &lt;br /&gt;
 fn conditional_unlisten(app: &amp;amp;tauri::AppHandle) {&lt;br /&gt;
    let handle = app.handle().clone();&lt;br /&gt;
 &lt;br /&gt;
    app.listen(&amp;quot;status-changed&amp;quot;, move |event| {&lt;br /&gt;
       // 条件に一致したらリスナーを解除&lt;br /&gt;
       if event.payload() == &amp;quot;\&amp;quot;ready\&amp;quot;&amp;quot; {&lt;br /&gt;
          println!(&amp;quot;準備完了 - リスナーを解除&amp;quot;);&lt;br /&gt;
          handle.unlisten(event.id);&lt;br /&gt;
       }&lt;br /&gt;
    });&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== emit_to : 特定WebViewへの送信 ==&lt;br /&gt;
&amp;lt;code&amp;gt;emit_to&amp;lt;/code&amp;gt; を使用すると、特定のWebViewにのみイベントを送信できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
複数のウインドウやWebViewが存在するアプリケーションで、特定のウインドウにのみ通知を送りたい場合に便利である。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Rustからの送信 ====&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::{AppHandle, Emitter};&lt;br /&gt;
 &lt;br /&gt;
 #[tauri::command]&lt;br /&gt;
 fn login(app: AppHandle, user: String, password: String) {&lt;br /&gt;
    // 認証処理&lt;br /&gt;
    let authenticated = user == &amp;quot;admin&amp;quot; &amp;amp;&amp;amp; password == &amp;quot;password&amp;quot;;&lt;br /&gt;
    let result = if authenticated { &amp;quot;loggedIn&amp;quot; } else { &amp;quot;invalidCredentials&amp;quot; };&lt;br /&gt;
 &lt;br /&gt;
    // &amp;quot;login&amp;quot; WebViewにのみ結果を送信&lt;br /&gt;
    // 第1引数: WebViewのラベル、第2引数: イベント名、第3引数: ペイロード&lt;br /&gt;
    app.emit_to(&amp;quot;login&amp;quot;, &amp;quot;login-result&amp;quot;, result).unwrap();&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== フロントエンドからの送信 ====&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { emitTo } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 import { getCurrentWebviewWindow } from &amp;#039;@tauri-apps/api/webviewWindow&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // 方法1 : emitTo 関数を使用&lt;br /&gt;
 // 第1引数: WebViewラベル、第2引数: イベント名、第3引数: ペイロード&lt;br /&gt;
 emitTo(&amp;#039;settings&amp;#039;, &amp;#039;settings-update-requested&amp;#039;, {&lt;br /&gt;
   key: &amp;#039;notification&amp;#039;,&lt;br /&gt;
   value: &amp;#039;all&amp;#039;&lt;br /&gt;
 });&lt;br /&gt;
 &lt;br /&gt;
 // 方法2 : WebviewWindow インスタンスから送信&lt;br /&gt;
 const appWebview = getCurrentWebviewWindow();&lt;br /&gt;
 appWebview.emitTo(&amp;#039;editor&amp;#039;, &amp;#039;file-changed&amp;#039;, {&lt;br /&gt;
   path: &amp;#039;/path/to/file&amp;#039;,&lt;br /&gt;
   contents: &amp;#039;file contents&amp;#039;&lt;br /&gt;
 });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== emit_filter : フィルタリング送信 ==&lt;br /&gt;
==== 概要 ====&lt;br /&gt;
&amp;lt;code&amp;gt;emit_filter&amp;lt;/code&amp;gt; を使用すると、条件に基づいて特定のWebViewにのみイベントを送信できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
複雑な条件で送信先を制御したい場合に使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 使用例 ====&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::{AppHandle, Emitter, EventTarget};&lt;br /&gt;
 use std::path::PathBuf;&lt;br /&gt;
 &lt;br /&gt;
 #[tauri::command]&lt;br /&gt;
 fn open_file(app: AppHandle, path: PathBuf) {&lt;br /&gt;
    // フィルタリングして特定のWebViewにのみ送信&lt;br /&gt;
    // &amp;quot;main&amp;quot; または &amp;quot;file-viewer&amp;quot; WebViewにのみ送信&lt;br /&gt;
    app.emit_filter(&amp;quot;open-file&amp;quot;, &amp;amp;path, |target| {&lt;br /&gt;
       match target {&lt;br /&gt;
          EventTarget::WebviewWindow { label } =&amp;gt; {&lt;br /&gt;
             label == &amp;quot;main&amp;quot; || label == &amp;quot;file-viewer&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          _ =&amp;gt; false  // 他のターゲットには送信しない&lt;br /&gt;
       }&lt;br /&gt;
    }).unwrap();&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== EventTarget の種類 ====&lt;br /&gt;
下表に、&amp;lt;code&amp;gt;emit_filter&amp;lt;/code&amp;gt; のフィルタ関数で使用できる &amp;lt;code&amp;gt;EventTarget&amp;lt;/code&amp;gt; の主な種類を示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ EventTarget の種類&lt;br /&gt;
! ターゲット !! 説明&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EventTarget::App&amp;lt;/code&amp;gt; || アプリケーション自体&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EventTarget::WebviewWindow { label }&amp;lt;/code&amp;gt; || 特定のWebViewウインドウ&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EventTarget::Webview { label }&amp;lt;/code&amp;gt; || 特定のWebView&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EventTarget::Window { label }&amp;lt;/code&amp;gt; || 特定のウインドウ&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== イベント名の命名規則 ==&lt;br /&gt;
==== 使用可能な文字 ====&lt;br /&gt;
イベント名には、以下に示す文字を使用できる。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 英数字 (a-z, A-Z, 0-9)&lt;br /&gt;
*: 大文字と小文字は区別される。&amp;lt;br&amp;gt;&lt;br /&gt;
* ハイフン (-)&lt;br /&gt;
*: 単語の区切りに使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
* アンダースコア (_)&lt;br /&gt;
*: スネークケース記法に使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 推奨される命名規則 ====&lt;br /&gt;
イベント名は、イベントの内容と送信元がわかるように命名することを推奨する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
推奨されるパターンを以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* ケバブケース (kebab-case) (推奨)&lt;br /&gt;
*: download-started、file-changed、user-logged-in&lt;br /&gt;
* スネークケース (snake_case)&lt;br /&gt;
*: download_started、file_changed&lt;br /&gt;
* ドメインプレフィックス付き&lt;br /&gt;
*: auth:login-success、file:change-detected&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 避けるべき命名 ====&lt;br /&gt;
* 空白を含む名前&lt;br /&gt;
*: download started (不正)&lt;br /&gt;
* 特殊文字を含む名前&lt;br /&gt;
*: download@started、download#progress (不正)&lt;br /&gt;
* あいまいな名前&lt;br /&gt;
*: event1、data、update (非推奨)&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== グローバルイベント ==&lt;br /&gt;
グローバルイベントは、アプリケーション全体で共有されるイベントである。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;emit&amp;lt;/code&amp;gt; で送信されたイベントは、全てのグローバルリスナーに配信される。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== 使用シーン ====&lt;br /&gt;
* アプリケーション全体の状態通知&lt;br /&gt;
*: テーマ変更、言語設定の変更等&lt;br /&gt;
* 複数ウインドウ間の通信&lt;br /&gt;
*: あるウインドウでの操作を他のウインドウに通知する。&lt;br /&gt;
* バックエンドからのブロードキャスト&lt;br /&gt;
*: 全フロントエンドに一斉通知を行う。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== listen_any : 全イベントの受信 ====&lt;br /&gt;
全てのイベント (フィルタやターゲットに関係なく) を受信するには、&amp;lt;code&amp;gt;listen_any&amp;lt;/code&amp;gt; を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { listenAny } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // 全てのイベントをリッスン&lt;br /&gt;
 const unlisten = await listenAny((event) =&amp;gt; {&lt;br /&gt;
   console.log(`イベント受信: ${event.event}`);&lt;br /&gt;
   console.log(`ペイロード:`, event.payload);&lt;br /&gt;
 });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== サンプルコード ==&lt;br /&gt;
==== ダウンロードマネージャーの例 ====&lt;br /&gt;
Rustバックエンドでダウンロードを管理して、フロントエンドに進捗を通知する例を以下に示す。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Rust (バックエンド) =====&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::{AppHandle, Emitter};&lt;br /&gt;
 use serde::Serialize;&lt;br /&gt;
 &lt;br /&gt;
 // イベントペイロードの型定義&lt;br /&gt;
 #[derive(Clone, Serialize)]&lt;br /&gt;
 #[serde(rename_all = &amp;quot;camelCase&amp;quot;)]&lt;br /&gt;
 struct DownloadStarted {&lt;br /&gt;
    url: String,&lt;br /&gt;
    download_id: usize,&lt;br /&gt;
    content_length: usize,&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #[derive(Clone, Serialize)]&lt;br /&gt;
 #[serde(rename_all = &amp;quot;camelCase&amp;quot;)]&lt;br /&gt;
 struct DownloadProgress {&lt;br /&gt;
    download_id: usize,&lt;br /&gt;
    chunk_length: usize,&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #[derive(Clone, Serialize)]&lt;br /&gt;
 #[serde(rename_all = &amp;quot;camelCase&amp;quot;)]&lt;br /&gt;
 struct DownloadFinished {&lt;br /&gt;
    download_id: usize,&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #[tauri::command]&lt;br /&gt;
 fn download_file(app: AppHandle, url: String) {&lt;br /&gt;
    let download_id = 1;&lt;br /&gt;
    let content_length = 10000;  // 実際はHTTPヘッダーから取得&lt;br /&gt;
 &lt;br /&gt;
    // ダウンロード開始通知&lt;br /&gt;
    app.emit(&amp;quot;download-started&amp;quot;, DownloadStarted {&lt;br /&gt;
       url: url.clone(),&lt;br /&gt;
       download_id,&lt;br /&gt;
       content_length,&lt;br /&gt;
    }).unwrap();&lt;br /&gt;
 &lt;br /&gt;
    // ダウンロード進捗のシミュレーション&lt;br /&gt;
    for chunk_length in [1500, 2500, 3000, 2000, 1000] {&lt;br /&gt;
       app.emit(&amp;quot;download-progress&amp;quot;, DownloadProgress {&lt;br /&gt;
          download_id,&lt;br /&gt;
          chunk_length,&lt;br /&gt;
       }).unwrap();&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // ダウンロード完了通知&lt;br /&gt;
    app.emit(&amp;quot;download-finished&amp;quot;, DownloadFinished {&lt;br /&gt;
       download_id,&lt;br /&gt;
    }).unwrap();&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== TypeScript (フロントエンド) =====&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { listen } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // イベントペイロードの型定義&lt;br /&gt;
 interface DownloadStarted {&lt;br /&gt;
   url: string;&lt;br /&gt;
   downloadId: number;&lt;br /&gt;
   contentLength: number;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 interface DownloadProgress {&lt;br /&gt;
   downloadId: number;&lt;br /&gt;
   chunkLength: number;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 interface DownloadFinished {&lt;br /&gt;
   downloadId: number;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // ダウンロードイベントのリスナーを設定&lt;br /&gt;
 async function setupDownloadListeners() {&lt;br /&gt;
   let totalDownloaded = 0;&lt;br /&gt;
   let expectedLength = 0;&lt;br /&gt;
 &lt;br /&gt;
   // ダウンロード開始イベント&lt;br /&gt;
   const unlistenStart = await listen&amp;lt;DownloadStarted&amp;gt;(&amp;#039;download-started&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
     console.log(`ダウンロード開始: ${event.payload.url}`);&lt;br /&gt;
     expectedLength = event.payload.contentLength;&lt;br /&gt;
     totalDownloaded = 0;&lt;br /&gt;
   });&lt;br /&gt;
 &lt;br /&gt;
   // ダウンロード進捗イベント&lt;br /&gt;
   const unlistenProgress = await listen&amp;lt;DownloadProgress&amp;gt;(&amp;#039;download-progress&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
     totalDownloaded += event.payload.chunkLength;&lt;br /&gt;
     const percentage = (totalDownloaded / expectedLength) * 100;&lt;br /&gt;
     console.log(`進捗: ${percentage.toFixed(1)}%`);&lt;br /&gt;
   });&lt;br /&gt;
  &lt;br /&gt;
   // ダウンロード完了イベント&lt;br /&gt;
   const unlistenFinished = await listen&amp;lt;DownloadFinished&amp;gt;(&amp;#039;download-finished&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
     console.log(`ダウンロード完了: ID ${event.payload.downloadId}`);&lt;br /&gt;
 &lt;br /&gt;
     // 不要になったリスナーを解除&lt;br /&gt;
     unlistenStart();&lt;br /&gt;
     unlistenProgress();&lt;br /&gt;
     unlistenFinished();&lt;br /&gt;
   });&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // 初期化時に呼び出し&lt;br /&gt;
 setupDownloadListeners();&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 注意事項 ==&lt;br /&gt;
==== パフォーマンスへの考慮 ====&lt;br /&gt;
* 高頻度のイベント送信は避ける。&lt;br /&gt;
*: 短時間に大量のイベントを送信すると、パフォーマンスに影響する。&lt;br /&gt;
*: 必要に応じてスロットリングやデバウンスを検討する。&lt;br /&gt;
* ペイロードのサイズを最小限にする。&lt;br /&gt;
*: 大きなオブジェクトを送信するとシリアライゼーションに時間が掛かる。&lt;br /&gt;
*: 必要なデータのみを含める。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== エラーハンドリング ====&lt;br /&gt;
* &amp;lt;code&amp;gt;emit&amp;lt;/code&amp;gt; のエラーを適切に処理する。&lt;br /&gt;
*: &amp;lt;code&amp;gt;emit&amp;lt;/code&amp;gt; は &amp;lt;code&amp;gt;Result&amp;lt;/code&amp;gt; を返すため、エラーハンドリングを行う。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 // 良い例 : エラーハンドリング&lt;br /&gt;
 if let Err(e) = app.emit(&amp;quot;my-event&amp;quot;, &amp;amp;payload) {&lt;br /&gt;
    eprintln!(&amp;quot;イベント送信エラー: {}&amp;quot;, e);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // 悪い例 : エラーを無視&lt;br /&gt;
 app.emit(&amp;quot;my-event&amp;quot;, &amp;amp;payload).unwrap();  // パニックの可能性&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== SPAでの注意点 ====&lt;br /&gt;
SPA (Single Page Application) では、ページ遷移してもリスナーが自動的に解除されない。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
コンポーネントのアンマウント時に必ず &amp;lt;code&amp;gt;unlisten&amp;lt;/code&amp;gt; を呼び出すこと。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
詳細を知りたい場合は、[[Tauriの基礎 - 型付きイベントとパターン]]のページを参照すること。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== once : 1度だけリッスン ====&lt;br /&gt;
イベントを1度だけ受信したい場合は、&amp;lt;code&amp;gt;once&amp;lt;/code&amp;gt; 関数を使用する。&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
 import { once } from &amp;#039;@tauri-apps/api/event&amp;#039;;&lt;br /&gt;
 &lt;br /&gt;
 // イベントを一度だけ受信&lt;br /&gt;
 await once(&amp;#039;app-ready&amp;#039;, (event) =&amp;gt; {&lt;br /&gt;
   console.log(&amp;#039;アプリケーションの準備が完了しました&amp;#039;);&lt;br /&gt;
 });&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
 use tauri::Manager;&lt;br /&gt;
 &lt;br /&gt;
 fn setup(app: &amp;amp;tauri::AppHandle) {&lt;br /&gt;
    // Rust での once&lt;br /&gt;
    app.once(&amp;quot;ready&amp;quot;, |event| {&lt;br /&gt;
       println!(&amp;quot;アプリケーション準備完了&amp;quot;);&lt;br /&gt;
    });&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 参考リンク ==&lt;br /&gt;
* [https://tauri.app/develop/calling-frontend/ Tauri公式ドキュメント - Calling the Frontend]&lt;br /&gt;
* [https://tauri.app/develop/calling-rust/ Tauri公式ドキュメント - Calling Rust]&lt;br /&gt;
* [https://docs.rs/tauri/latest/tauri/event/index.html Tauri API Reference - Events]&lt;br /&gt;
* [[Tauriの基礎 - Commands]]&lt;br /&gt;
*: リクエスト・レスポンス型の通信&lt;br /&gt;
* [[Tauriの基礎 - 型付きイベントとパターン]]&lt;br /&gt;
*: 型安全なイベント処理とReactパターン&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{#seo:&lt;br /&gt;
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki&lt;br /&gt;
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Tauri,Rust,React,TypeScript,Event,emit,listen,WebView,Desktop App,Desktop Application&lt;br /&gt;
|description={{PAGENAME}} - TauriのイベントシステムによるRustとReact間の双方向通信について解説 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux&lt;br /&gt;
|image=/resources/assets/MochiuLogo_Single_Blue.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
__FORCETOC__&lt;br /&gt;
[[カテゴリ:Rust]]&lt;/div&gt;</summary>
		<author><name>Wiki</name></author>
	</entry>
</feed>