iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
Rust

用 Tauri 打造你的應用程式系列 第 16

[Day 16] Plugin (一):Store

  • 分享至 

  • xImage
  •  

在我們之前的文章中 (Day 10),曾經提到了如何使用 Tauri 內建的 State 功能來管理應用程式的狀態。State 非常適合用來處理應用程式運行期間的即時狀態,但當應用程式關閉後,這些狀態就會消失。如果我們希望某些資料能夠被永久保存,例如使用者的設定、視窗大小與位置等,這時候就需要一個能夠將資料寫入檔案的解決方案。

今天,我們將介紹一個官方維護的插件 tauri-plugin-store,它提供了一個簡單好用的 Key-Value 儲存方案,讓我們可以輕鬆地在前端與後端之間讀寫持久化的資料。

State vs. Store:如何選擇?

在深入 tauri-plugin-store 之前,讓我們先快速釐清一下它與之前提到的 State 的區別:

  • tauri::State:

    • 用途:用於管理應用程式運行時的記憶體狀態。
    • 生命週期:資料僅存在於應用程式的生命週期內,一旦應用程式關閉,狀態就會遺失。
    • 優點:讀寫速度快,因為是直接操作記憶體。適合存放需要頻繁更新的臨時性資料。
    • 範例:應用程式的計數器、目前主題、使用者是否登入的狀態旗標。
  • tauri-plugin-store:

    • 用途:提供持久化的 Key-Value 儲存。
    • 生命週期:資料會被寫入到磁碟上的檔案中 (通常是 JSON 格式),即使應用程式關閉或重新啟動,資料依然存在。
    • 優點:輕鬆實現資料持久化,跨應用程式會話共享資料。
    • 範例:使用者偏好設定 (如語言、主題)、視窗大小與位置、快取資料。

簡單來說,如果你需要一個關閉程式後就消失的暫時狀態,用 State;如果你需要一個能永久保存的設定檔,那就用 store 插件。這兩者並不互斥,在一個複雜的應用中,通常會兩者並用。

不同作業系統會把資料儲存在不同位置,以 Windows 為例,會儲存在 AppData 的 Roaming 資料夾中。

如何安裝 tauri-plugin-store

Tauri 的 plugin 的安裝都很簡單,只要下這個指令就可以自動安裝了:

npm run tauri add store

安裝完之後,理論上就可以直接使用了。之後如果有需要,記得去調整 capabilities,給予合適的權限、預設是給予 store:default 權限:

{
  "permissions": [
    ...,
+   "store:default",
  ]
}

基礎範例:前後端共享設定

讓我們來實作一個非常簡單的範例:在後端寫入一個設定值,然後在前端讀取它。

前端 (JavaScript / TypeScript)

我們可以在任何一個前端元件中,透過 Store class 來操作資料。預設情況下,它會將資料儲存在一個名為 store.json 的檔案中。讓我們來調整一下預設範例:

import { ref, onMounted } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { Store } from "@tauri-apps/plugin-store";

const greetMsg = ref("");
const name = ref("");
const greetName = ref("");
let store: Store;

async function greet() {
  // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
  greetMsg.value = await invoke("greet", { name: name.value });
  greetName.value = name.value;
  
  // // 也可以直接在前端儲存姓名到 store
  // if (store) {
  //   await store.set("name", name.value);
  //   await store.save();
  // }
}

// 在元件掛載時載入 store 中的姓名
onMounted(async () => {
  // 載入 store (也可以不給參數,預設會是 store.json)
  store = await Store.load("user-data.json");
  
  // 檢查是否有儲存的姓名
  const storedName = await store.get<string>("name");
  if (storedName) {
    greetName.value = storedName;
  }
});

並在 <template> 中找個地方呈現一下 greetName

<h2 v-if="greetName !== ''">Welcome back~ {{ greetName }}~</h2>

後端 (Rust)

在後端,我們通常會在 setup 或是某個 command 中存取 store。

讓我們直接修改範例 greet

use tauri::AppHandle;
use tauri_plugin_store::StoreExt;

#[tauri::command]
fn greet(name: &str, app: AppHandle) -> Result<String, String> {
    // 取得 store 實例
    let store = app.store("user-data.json").map_err(|e| e.to_string())?;
    
    // 儲存姓名到 store
    store.set("name", serde_json::Value::String(name.to_string()));
    
    // 儲存 store 到檔案
    if let Err(e) = store.save() {
        return Err(format!("Failed to save store: {}", e));
    }
    
    Ok(format!("Hello, {}! You've been greeted from Rust!", name))
}

這樣就完成了!

簡單 Demo

  1. 一開始什麼都沒有

  2. 接下來隨便輸入一個名字,按下 Greet 按鈕。可以看到上面多了一行副標題,輸入框下方也有一行小字 (原本的範例就有的)。

  3. 接下來,關閉程式後,再次打開。就會自動載入 Store,顯示名字在副標題。

最佳實踐與注意事項

使用 tauri-plugin-store 時,有幾個重要的最佳實踐需要注意。首先,記得呼叫 save() 方法來確保資料真正寫入磁碟,否則資料可能只存在於記憶體中。其次,合理地組織資料結構,避免儲存過於複雜的巢狀物件,這有助於提升讀寫效能。

此外,考慮到使用者隱私,敏感資料應該經過適當的加密處理,而不是直接以明文形式儲存。對於大量資料的儲存,建議考慮使用更專業的資料庫解決方案。

小結

透過這個簡單的範例,我們可以看到 tauri-plugin-store 如何輕鬆地在前後端之間建立一個持久化的資料橋樑。這對於儲存使用者設定、應用程式配置等場景非常有用。

今天我們介紹了 store 插件的用途、安裝方式以及一個基礎的範例。在接下來的文章中,我們會繼續探索更多實用的 Tauri 插件!


上一篇
[Day 15] 系統匣圖示 System Tray
下一篇
[Day 17] Plugin (二):File System
系列文
用 Tauri 打造你的應用程式17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言