Tauri是一套工具,让你使用前端框架构建跨平台的桌面应用。当与React和Vite结合时,它可以用来为所有桌面平台构建极快的二进制文件。
开发人员可以使用Tauri用网络技术编写安全、精简、快速的跨平台桌面应用。对许多开发者来说,Electron通常是这些应用程序的首选框架,但Tauri现在已经做好了竞争的准备。
在这篇文章中,我们将建立一个简单的Pomodoro计时器,我邀请你按照自己的节奏来学习这个教程。
Tauri是什么?
它 "快得惊人"(这是他们说的,不是我说的;但请点击链接查看基准,自己决定),因为它使用Rust作为后端(相对于Node),产生的二进制文件更小,而且比Node更安全。
它使用底层操作系统提供的WebView来渲染应用程序的用户界面--这也是应用程序的二进制文件较小的原因之一(与电子相比)。来自Tauri工具包的WRY库提供了一个统一的接口来与不同操作系统提供的WebView交互。WRY库使用Tao crate进行跨平台的窗口管理。
Tauri把这一切结合在一起,使开发者能够编写强大的、性能良好的桌面应用程序。
先决条件
在我们开始之前,我们需要安装一些东西。
锈
要安装Rust,请打开你的终端并运行:
curl --proto '=https' --tlsv1.2 -sSf [https://sh.rustup.rs](https://sh.rustup.rs) | sh
如果你是在Windows上,请按照以下说明进行安装。
npm
npm是Node的一个软件包管理器。它与Node捆绑在一起,所以如果你的系统上安装了Node,你很可能也会有npm。
如果你没有Node,可以用Homebrew安装它。
brew install node
在安装了npm和Rust之后,我们就可以开始使用Tauri开发应用程序了。
用create-tauri-app搭建一个Tauri应用的支架
由于先决条件已经安装,我们可以开始开发Pomodoro计时器的桌面应用程序。Tauri的人们用 create-tauri-appnpm包,使应用程序的脚手架搭建变得非常容易。
要开始工作,请运行:
npx create-tauri-app
运行这个命令后,你将被要求输入一些信息:
- 项目的名称
- 窗口的标题,应用程序将在其中加载
- UI配方
- 要使用的模板
对于这个教程应用程序,我使用了以下内容,见下文
- 项目名称为 "pomodoro"
- 窗口的标题为 "Pomodoro Timer App"。
- UI配方为 "create-vite"
- 模板使用 "react-ts"

点击回车键将安装所有必要的软件包,并在与项目名称相同的文件夹下输出一个脚手架项目。
现在我们都准备好了,可以第一次运行这个项目了
要运行该项目,请运行:
cd pomodoro // cding into the project folder
npm run tauri dev //running the app
这将首先启动前端服务器,然后将下载crates(如果需要)并编译Rust后端。一旦编译完成,没有任何错误,应用程序就会启动,你会看到像这样的东西。

项目文件夹包含很多重要的文件和文件夹。在本教程中,我们要处理的两个文件是。
src文件夹和。src-tauri/tauri.config.json文件
(注意:第一次运行该应用程序将需要一些时间,因为该应用程序需要下载和编译必要的Rust crates)
(注意:对于使用macOS进行开发的人来说--如果你运行命令来启动应用,并且应用窗口出现在全屏应用上,你将无法移动应用窗口。这是一个已知的错误,可以在这里进行追踪)
构建前台
我们将使用ChakraUI来实现UI组件和风格设计。要设置ChakraUI,请遵循他们的入门指南。
我们将在下面构建UI:

以下是我们的应用程序的要求:
- 应该有一个开始和暂停按钮,启动和停止定时器。
- 一旦定时器达到0,就触发一个通知给用户。
- 可以选择间隔长度,即:15分钟、30分钟和60分钟。
- 一个复位按钮,将计时器重置为初始值。
要开始,请到src/App.tsx:
// src/App.tsx
import { Button, Flex, Text } from "@chakra-ui/react";
import { useEffect, useState } from "react";
function App() {
const [time, setTime] = useState(0);
const [timerStart, setTimerStart] = useState(false);
const buttons = [
{
value: 900,
display: "15 minutes",
},
{
value: 1800,
display: "30 minutes",
},
{
value: 3600,
display: "60 minutes",
},
];
const toggleTimer = () => {
setTimerStart(!timerStart);
};
useEffect(() => {
const interval = setInterval(() => {
if (timerStart) {
if (time > 0) {
setTime(time - 1);
} else if (time === 0) {
// TODO: Send notification to user.
clearInterval(interval);
}
}
}, 1000);
return () => clearInterval(interval);
}, [timerStart, time]);
return (
<div className="App" style={{ height: "100%" }}>
<Flex
background="gray.700"
height="100%"
alignItems="center"
flexDirection="column"
>
<Text color="white" fontWeight="bold" marginTop="20" fontSize="35">
Pomodoro Timer
</Text>
<Text fontWeight="bold" fontSize="7xl" color="white">
{`${
Math.floor(time / 60) < 10
? `0${Math.floor(time / 60)}`
: `${Math.floor(time / 60)}`
}:${time % 60 < 10 ? `0${time % 60}` : time % 60}`}
</Text>
<Flex>
<Button
width="7rem"
background="tomato"
color="white"
onClick={toggleTimer}
>
{!timerStart ? "Start" : "Pause"}
</Button>
{/* TODO: Add Button to reset timer */}
</Flex>
<Flex marginTop={10}>
{buttons.map(({ value, display }) => (
<Button
marginX={4}
background="green.300"
color="white"
onClick={() => {
setTimerStart(false);
setTime(value);
}}
>
{display}
</Button>
))}
</Flex>
</Flex>
</div>
);
}
export default App;
在这里,我们使用ChakraUI的内置组件来设置按钮和文本的布局。
useEffect 钩子中的setTimeout ,通过每过一秒设置状态来驱动用户界面。
该效果重新运行:
- 当用户点击持续时间按钮时(这设置了
timerStart和time的状态值) - 当用户点击 "开始/暂停"按钮时。(这设置了
timerStart状态值) - 每过一秒。(
setTimeout触发对time值的更新,见第29行)
为了以一致的格式(mm:ss)显示时间,我们需要做一些数学体操。
这当然不完美,但它能完成工作。
这里有两个待办事项:
- 添加一个复位按钮
- 在点击这个按钮时,会触发一个本地对话框,要求用户确认该操作。
- 添加一个通知触发器
- 当定时器达到0时,需要向用户发送通知
但是,在我们开始处理这些项目之前,我们需要在src-tauri/tauri.config.json 文件中添加我们将要调用的本地API。如果我们不做这个步骤,我们将无法触发本地元素。
因此,前往src-tauri/tauri.config.json ,并将此添加到tauri.allowlist:
"tauri": {
"allowlist": {
// other allowed items
"notification": {
"all": true
},
"dialog": {
"all": true
}
}
}
(注意:为了简单起见,dialog 和notification 的一切都被允许。我们可以更具体一些,以避免不必要的访问)
触发通知并添加一个重置计时器的按钮
// src/App.tsx
import { Button, Flex, Text } from "@chakra-ui/react";
import { useEffect, useState } from "react";
+ import { sendNotification } from "@tauri-apps/api/notification";
+ import { ask } from "@tauri-apps/api/dialog";
function App() {
const [time, setTime] = useState(0);
const [timerStart, setTimerStart] = useState(false);
const buttons = [
{
value: 900,
display: "15 minutes",
},
{
value: 1800,
display: "30 minutes",
},
{
value: 3600,
display: "60 minutes",
},
];
const toggleTimer = () => {
setTimerStart(!timerStart);
};
+ const triggerResetDialog = async () => {
+ let shouldReset = await ask("Do you want to reset timer?", {
+ title: "Pomodoro Timer App",
+ type: "warning",
+ });
+ if (shouldReset) {
+ setTime(900);
+ setTimerStart(false);
+ }
+ };
useEffect(() => {
const interval = setInterval(() => {
if (timerStart) {
if (time > 0) {
setTime(time - 1);
} else if (time === 0) {
+ sendNotification({
+ title: `Time's up!`,
+ body: `Congrats on completing a session!
Tauri提供了一个JS/TS API包,用于从Rust后端调用函数。必要的包已经被create-tauri-app ,所以我们可以直接导入npm包并在我们的前端代码中使用它。
用于触发一个通知
- 从通知模块中导入
sendNotification函数 - 在前台代码中调用该函数(见第42行)。更多关于API的信息请点击这里
对于触发一个对话框
- 从对话框模块中导入
ask函数 - 在前端代码中调用该函数。第一个参数是将出现在对话框中的文本(见第27行)。这里有更多关于API的信息
- 由于它需要用户输入,该函数返回一个带有布尔值的承诺,因此我们可以
await,以获得用户点击的值 - 如果用户接受,我们将时间值重置为15分钟,如果定时器已经在运行,则停止它
最后运行该应用程序,运行
npm run tauri dev

构建应用程序
构建用于分发的应用程序可以通过运行来实现。
cargo tauri build
这将会构建应用程序并创建一个二进制文件。src-tauri/target/release
现在,该应用程序已经准备好发布了!
总结
就这样吧!感谢你阅读我关于使用Vite和React的Tauri构建应用程序的演练教程。