Xz's blog Xz's blog
首页
时间序列
多模态
合成生物学
其他方向
生活
工具相关
PyTorch
导航站

Xu Zhen

首页
时间序列
多模态
合成生物学
其他方向
生活
工具相关
PyTorch
导航站
  • Rust

  • Rust-Windows 窗口自动化

  • Tauri

    • WebView
    • 项目结构
    • Tauri与React的第一个程序
      • React 第一个程序
        • 1. 导入 (Imports)
        • 2. 组件定义 (Component Definition)
        • 3. 状态管理 (State Management)
        • 4. 与后端通信的函数 (Function for Backend Communication)
        • 5. 界面渲染 (UI Rendering with JSX)
        • 总结
      • Rust 第一个程序
        • 1. greet 函数 (The greet Command)
        • 2. run 函数 (The Application Entry Point)
        • 代码整体流程
  • C++

  • Claude Code

  • Liunx相关

  • Windows相关

  • IDE

  • Conda

  • Docker

  • VMware虚拟机

  • Python常用代码片段

  • 工具相关
  • Tauri
xuzhen
2025-08-17
目录

Tauri与React的第一个程序

# React 第一个程序

src\App.tsx文件如下(默认生成的代码),下面详细讲解这个文件。这段代码是一个使用 React 框架和 Tauri 构建的桌面应用的简单前端界面。

import { useState } from "react";
import reactLogo from "./assets/react.svg";
import { invoke } from "@tauri-apps/api/core";
import "./App.css";

function App() {
  const [greetMsg, setGreetMsg] = useState("");
  const [name, setName] = useState("");

  async function greet() {
    // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
    setGreetMsg(await invoke("greet", { name }));
  }

  return (
    <main className="container">
      <h1>Welcome to Tauri + React</h1>

      <div className="row">
        <a href="https://vite.dev" target="_blank">
          <img src="/vite.svg" className="logo vite" alt="Vite logo" />
        </a>
        <a href="https://tauri.app" target="_blank">
          <img src="/tauri.svg" className="logo tauri" alt="Tauri logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <p>Click on the Tauri, Vite, and React logos to learn more.</p>

      <form
        className="row"
        onSubmit={(e) => {
          e.preventDefault();
          greet();
        }}
      >
        <input
          id="greet-input"
          onChange={(e) => setName(e.currentTarget.value)}
          placeholder="Enter a name..."
        />
        <button type="submit">Greet</button>
      </form>
      <p>{greetMsg}</p>
    </main>
  );
}

export default App;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

下面我们来逐行分解解释:

# 1. 导入 (Imports)

import { useState } from "react";
import reactLogo from "./assets/react.svg";
import { invoke } from "@tauri-apps/api/core";
import "./App.css";
1
2
3
4
  • import { useState } from "react";
    • 这是从 React 库中导入一个名为 useState 的 "Hook"。Hook 是让你在函数组件里“钩入” React 特性和状态的函数。useState 用于在组件中添加和管理组件的内部状态。
  • import reactLogo from "./assets/react.svg";
    • 这行代码导入了位于 ./assets/ 目录下的 react.svg 图片文件。在代码中,reactLogo 将会是一个指向这个图片路径的变量,可以用于在 <img> 标签中显示图片。
  • import { invoke } from "@tauri-apps/api/core";
    • 这是 Tauri 框架的核心部分。invoke 函数是从 Tauri 的 JavaScript API 中导入的。它的作用是调用你在 Rust 后端代码中定义的命令 (command)。这是实现前端和后端通信的关键。
  • import "./App.css";
    • 这行代码导入了组件的 CSS 样式文件,用于美化界面的外观。

# 2. 组件定义 (Component Definition)

function App() {
  // ... 组件内部逻辑和 JSX ...
}

export default App;
1
2
3
4
5
  • function App() { ... }
    • 这定义了一个名为 App 的函数式组件。在 React 中,组件是构成用户界面的独立且可复用的代码块。这个 App 组件是整个应用的主组件。
  • export default App;
    • 这行代码将 App 组件导出,使其可以在其他文件中被导入和使用(通常是在 main.jsx 或 index.js 中)。

# 3. 状态管理 (State Management)

const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
1
2
  • 这里使用了我们之前导入的 useState Hook 来创建两个状态变量:
    • const [greetMsg, setGreetMsg] = useState("");:
      • greetMsg 是一个状态变量,用于存储从后端返回的问候消息。它的初始值被设为一个空字符串 ""。
      • setGreetMsg 是一个函数,用来更新 greetMsg 的值。当这个函数被调用时,React 会重新渲染组件以显示更新后的消息。
    • const [name, setName] = useState("");:
      • name 是另一个状态变量,用于存储用户在输入框中输入的名字。它的初始值也是一个空字符串。
      • setName 是用来更新 name 值的函数。

# 4. 与后端通信的函数 (Function for Backend Communication)

async function greet() {
  // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
  setGreetMsg(await invoke("greet", { name }));
}
1
2
3
4
  • async function greet() { ... }
    • 这里定义了一个名为 greet 的异步函数。使用 async 关键字是因为它内部调用了 invoke,而 invoke 是一个返回 Promise 的异步操作。
  • setGreetMsg(await invoke("greet", { name }));
    • 这是整个应用的核心交互逻辑。
    • invoke("greet", { name }):这行代码调用了 Tauri 的 invoke 函数。
      • 第一个参数 "greet" 是你在 Rust 后端定义的命令的名称。
      • 第二个参数 { name } 是一个对象,它包含了要传递给后端命令的参数。在这里,它把当前 name 状态变量的值传递给了后端。
    • await:关键字等待 invoke 函数完成并返回结果(也就是 Rust 后端 greet 命令的返回值)。
    • setGreetMsg(...):一旦从后端获取到返回的问候消息,就使用 setGreetMsg 函数来更新 greetMsg 状态,从而在界面上显示出来。

# 5. 界面渲染 (UI Rendering with JSX)

return (
  <main className="container">
    {/* ... JSX 内容 ... */}
  </main>
);
1
2
3
4
5
  • return (...)
    • return 语句内部的内容是 JSX (JavaScript XML),它描述了组件的 UI 结构。它看起来很像 HTML。
  • <main className="container">
    • 这是组件的根元素。
  • <h1>Welcome to Tauri + React</h1>
    • 一个一级标题。
  • Logos and Links:
    <div className="row">
      <a href="https://vite.dev" target="_blank">
        <img src="/vite.svg" className="logo vite" alt="Vite logo" />
      </a>
      // ... Tauri and React logos
    </div>
    
    1
    2
    3
    4
    5
    6
    • 这部分显示了 Vite、Tauri 和 React 的 Logo,并为它们添加了指向各自官网的链接。
  • 表单 (Form):
    <form
      className="row"
      onSubmit={(e) => {
        e.preventDefault();
        greet();
      }}
    >
      <input
        id="greet-input"
        onChange={(e) => setName(e.currentTarget.value)}
        placeholder="Enter a name..."
      />
      <button type="submit">Greet</button>
    </form>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    • onSubmit={(e) => { ... }}:当表单被提交时(通过点击按钮或按回车),这个函数会被调用。
      • e.preventDefault();:阻止表单提交的默认行为(即刷新页面)。
      • greet();:调用我们前面定义的 greet 函数,来向后端发送请求。
    • <input ... />:一个输入框。
      • onChange={(e) => setName(e.currentTarget.value)}:这是一个非常重要的部分。每当输入框的内容发生改变时,它会调用 setName 函数,用输入框的当前值来更新 name 状态。这实现了输入框和 name 状态的绑定。
      • placeholder="Enter a name...":输入框中的提示文字。
    • <button type="submit">Greet</button>:一个提交按钮。
  • 显示问候消息 (Displaying the Greeting Message):
    <p>{greetMsg}</p>
    
    1
    • 这个 <p> 标签用来显示 greetMsg 状态变量的内容。最初它是空的,当 greet 函数成功从后端获取消息并调用 setGreetMsg 更新状态后,新的问候语就会显示在这里。

# 总结

这个 App 组件的工作流程如下:

  1. 渲染界面:显示标题、三个 Logo、一个带输入框和按钮的表单,以及一个用于显示消息的空段落。
  2. 用户输入:用户在输入框中输入自己的名字。每次输入都会触发 onChange 事件,调用 setName 来更新 name 状态。
  3. 提交表单:用户点击 "Greet" 按钮或者按回车键提交表单。
  4. 调用后端:表单的 onSubmit 事件被触发,它会调用 greet 函数。
  5. 与 Rust 通信:greet 函数使用 Tauri 的 invoke API 调用 Rust 后端中名为 "greet" 的命令,并将当前 name 状态作为参数传递过去。
  6. 接收和更新:greet 函数等待后端处理并返回一个字符串(例如 "Hello, [name]!")。
  7. 显示结果:greet 函数用返回的字符串调用 setGreetMsg,更新 greetMsg 状态。React 检测到状态变化,自动重新渲染界面,将新的问候消息显示在 <p> 标签中。

# Rust 第一个程序

这是一个典型的 src-tauri/src/lib.rs 或 src-tauri/src/main.rs 文件,是 Tauri 应用的 Rust 入口点。

这段 Rust 代码是 Tauri 应用的后端部分,它与我们之前分析的前端 React 代码协同工作。

// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

我们来逐段解析:

# 1. greet 函数 (The greet Command)

// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}
1
2
3
4
5
  • #[tauri::command]
    • 这是一个 Rust 的 "属性宏 (attribute macro)"。它告诉 Tauri 编译器,下面的 greet 函数是一个“命令 (Command)”。.
    • Tauri 会自动生成必要的“粘合代码”,使得这个 Rust 函数可以从 JavaScript 前端通过 invoke 函数来调用。
  • fn greet(name: &str) -> String
    • 这定义了一个名为 greet 的公共函数。
    • name: &str:这个函数接受一个名为 name 的参数,它的类型是 &str(一个字符串切片),这是 Rust 中处理字符串的常见高效方式。前端通过 invoke("greet", { name: "..." }) 传过来的 name 值会在这里被接收。
    • -> String:这个函数会返回一个 String 类型的值。这个返回值将被序列化并通过 invoke 的 Promise 解析,最终传递回 JavaScript 前端。
  • format!("Hello, {}! You've been greeted from Rust!", name)
    • 这是 Rust 的一个内置宏,用于创建格式化的字符串。
    • 它会将第一个参数(格式化字符串)中的 {} 占位符替换为后面参数(这里是 name 变量)的值。
    • 所以,如果前端传来 "React",这个函数就会构造并返回字符串 "Hello, React! You've been greeted from Rust!"。

简而言之,greet 函数就是前端 React 代码中 invoke("greet", { name }) 调用的具体实现。

# 2. run 函数 (The Application Entry Point)

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
1
2
3
4
5
6
7
8
  • #[cfg_attr(mobile, tauri::mobile_entry_point)]
    • 这是一个条件编译属性。它的意思是:如果编译目标是 mobile(移动端),那么就应用 #[tauri::mobile_entry_point] 这个属性宏。
    • 这对于构建跨桌面和移动端的 Tauri 应用至关重要,它为移动平台指定了正确的入口点。
  • pub fn run()
    • 这是应用程序的主入口函数。当你的 Tauri 应用启动时,这个 run 函数会被执行。
  • tauri::Builder::default()
    • 这会创建一个 Tauri 应用的构建器(Builder)实例。 构建器模式允许你用链式调用的方式来配置和初始化你的应用程序。
  • .plugin(tauri_plugin_opener::init())
    • 这行代码注册并初始化了一个名为 tauri-plugin-opener 的插件。
    • 这个插件的功能是允许你的应用打开外部链接或系统文件管理器中的文件。 比如,当你在前端点击 Vite 或 Tauri 的 Logo 链接时,就是这个插件在起作用,它会调用系统的默认浏览器来打开该网页。
  • .invoke_handler(tauri::generate_handler![greet])
    • 这是将前端和后端命令连接起来的关键步骤。
    • invoke_handler 方法用于注册所有你希望从 JavaScript 调用的 Rust 命令。
    • tauri::generate_handler![greet] 是一个宏,它会接收一个或多个你用 #[tauri::command] 标记的函数(这里是 greet),并为它们生成一个统一的处理器。 这个处理器会根据前端传来的命令名称(字符串 "greet")来调用相应的 Rust 函数。
  • .run(tauri::generate_context!())
    • .run() 是构建器链上的最后一步,它会最终构建并运行应用程序。
    • tauri::generate_context!() 是另一个宏,它会在编译时读取 tauri.conf.json 配置文件,并生成一个包含所有应用配置的上下文(Context)对象。 这个上下文对象包含了窗口标题、标识符等所有应用的元数据。
  • .expect("error while running tauri application")
    • .run() 方法会返回一个 Result 类型。在 Rust 中,Result 表示一个操作可能成功也可能失败。
    • .expect() 是处理 Result 的一种简单方式。如果 run() 成功,它什么也不做。如果 run() 返回一个错误(Error),程序就会 "panic"(恐慌,即崩溃),并显示这里的错误信息。这在开发中很常见,但在生产应用中通常会用更优雅的方式处理错误。

# 代码整体流程

  1. 当用户执行编译好的 Tauri 应用时,run 函数被调用。
  2. tauri::Builder 开始构建应用。
  3. opener 插件被注册,使得应用具备了打开外部链接的能力。
  4. greet 命令通过 invoke_handler 被注册,Tauri 知道了有一个名为 "greet" 的命令可以从前端调用。
  5. 应用配置从 tauri.conf.json 文件中加载。
  6. .run() 启动了应用,创建了窗口,并加载了前端的 React 代码。
  7. 此时,应用处于运行状态,等待前端的交互。当用户在 React 界面中输入名字并点击 "Greet" 按钮时,前端的 invoke("greet", ...) 被触发,Tauri 的核心接收到这个调用请求,并将其路由到我们刚刚注册的 Rust greet 函数,最终将执行结果返回给前端。
#none
上次更新: 2025/08/19, 08:47:47

← 项目结构 多线程之 std::condition_variable→

最近更新
01
Linux 通过Windows代理上网
09-18
02
vscode远程使用copilot和codex(内网环境)
09-18
03
跨机器克隆环境
09-18
更多文章>
Theme by Vdoing | Copyright © 2025-2025 Xu Zhen | 鲁ICP备2025169719号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式