集成 Vue 3
本教程共 48 篇 · 第 16 篇 · 更新于 2026-08-09 · 约 7 分钟阅读
本节目标:学完能用官方脚手架生成一个 Vue 3 模板,理解 Vite 开发端口为什么要「锁死」,并能在 Vue 组件里正确调用 Tauri 的
invoke。
当界面变复杂,原生三件套就显得吃力了。Vue 3 是目前最流行的渐进式前端框架之一,组件化、响应式数据用起来很顺手。好消息是:Tauri 和 Vue 的集成,本质上和上一章的原生前端没有区别——底层依旧是 WebView 加载页面、依旧靠 invoke 调 Rust。变了的只是前端代码的组织方式。本章只讲「集成机制」和「调用方式」,不带着做一个完整产品。
用脚手架生成 Vue 3 模板
Tauri 官方提供了一个交互式脚手架 create-tauri-app,它能帮你把前端和 Rust 两端一次性搭好,并内置了 Vue 3 模板。运行命令(版本以官方最新为准):
npm create tauri-app@latest
命令会问你几个问题:项目名、前端包管理器,以及最关键的——「选哪个前端模板」。在列表里选 Vue(TypeScript) 或 Vue(JavaScript) 即可(带 TypeScript 的模板类型提示更好,推荐新手选它)。脚手架会自动做三件事:创建 src/ 作为 Vue 前端、创建 src-tauri/ 作为 Rust 后端、并装好 @tauri-apps/api 和 @tauri-apps/cli 这两个包。
生成完毕后,目录结构大致是:
my-vue-app/
├── src/ # Vue 前端源码
│ ├── App.vue # 根组件
│ ├── main.ts # 入口,挂载 Vue 应用
│ └── vite.config.ts # Vite 配置
├── src-tauri/ # Rust 后端
│ ├── tauri.conf.json
│ └── src/lib.rs
└── package.json
你平时写界面都在 src/ 里,Rust 相关的事都在 src-tauri/ 里,两者通过配置和 IPC 连起来。启动开发用 npm run tauri dev,构建发布用 npm run tauri build。
关键配置:锁死 Vite 端口
Vue 模板默认用 Vite 做开发服务器和打包工具。这里有个集成时的「必设点」:Tauri 在开发模式下要靠一个固定的网址(devUrl)找到你的前端,而 Vite 默认端口是「占到哪个算哪个」,还可能因为端口被占用自动换到 5174、5175。一旦端口飘了,Tauri 就接不上了。
解决办法是在 src/vite.config.ts 里把端口固定,并开启 strictPort(端口被占用就直接报错,而不是换端口):
// src/vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
clearScreen: false,
server: {
port: 5173,
strictPort: true,
},
});
对应的,tauri.conf.json 里的 build 配置要和这个端口对齐:
{
"build": {
"beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build",
"devUrl": "http://localhost:5173",
"frontendDist": "../dist"
}
}
Tip
clearScreen: false是 Vue 模板的常见写法,它能防止 Vite 清屏,让 Tauri 的 Rust 编译日志和 Vite 的日志互不覆盖,调试时看得更清楚。它不影响功能,但建议保留。
在 Vue 组件里调用 Tauri API
集成机制讲完,剩下的就是「在 Vue 里怎么写那句 invoke」。答案和原生前端完全一样:从 @tauri-apps/api/core 引入 invoke。区别只是它现在写在 Vue 的 <script setup> 里。
<!-- src/App.vue -->
<script setup lang="ts">
import { ref } from 'vue';
import { invoke } from '@tauri-apps/api/core';
const name = ref('');
const reply = ref('');
async function greet() {
// 调用 Rust 端的 greet 命令,参数用对象传
reply.value = await invoke('greet', { name: name.value });
}
</script>
<template>
<h1>Vue 3 + Tauri</h1>
<input v-model="name" placeholder="输入你的名字" />
<button @click="greet">打招呼</button>
<p>{{ reply }}</p>
</template>
后端 src-tauri/src/lib.rs 里,greet 命令的定义和前面章节一致:
#[tauri::command]
fn greet(name: String) -> String {
format!("你好,{}!来自 Rust 的问候。", name)
}
invoke 返回的是 Promise,所以在 Vue 的 async 函数里用 await 取值,再赋给 ref 驱动的响应式变量,界面就自动更新了。这就是 Vue 响应式 + Tauri 原生能力的标准配合方式。
Note别忘了第 14 章提过的安全模型:这个
greet命令需要在src-tauri/capabilities/的能力文件里被授权,前端才能调得通。脚手架生成的 Vue 模板已经把默认命令和core:default权限配好了,你新增命令时记得补上权限,否则会收到权限错误。
不止 invoke:其它 API 模块
@tauri-apps/api 不止有 core。在 Vue 组件里,你同样可以按模块引入其它能力,比如操作当前窗口:
import { getCurrentWindow } from '@tauri-apps/api/window';
// 隐藏当前窗口
await getCurrentWindow().hide();
再比如收发事件(对应第 14 章的「事件」通道):
import { listen } from '@tauri-apps/api/event';
await listen('progress', (event) => {
console.log(event.payload);
});
这些 API 的引入方式和 invoke 一模一样,都是标准 ES 模块导入,在 <script setup> 里直接 import 即可。需要注意:部分能力(如文件系统、进程、对话框)属于独立插件,除了 import,还要在 Rust 端 .plugin(...) 注册、并在能力文件里授权——这属于插件章节的内容,这里先知道「API 按模块引入」这个统一规律即可。
小结
Vue 3 与 Tauri 的集成可以浓缩成三句话:用 create-tauri-app 选 Vue 模板一键生成;在 vite.config.ts 里把端口 strictPort 锁死,并和 tauri.conf.json 的 devUrl 对齐;在 Vue 组件里 import { invoke } from '@tauri-apps/api/core' 调用 Rust。其余所有「原生能力」,都只是换个文件、换个模块名去 import,底层机制始终不变。
至此,你已经走完了从「概念」到「能构建一个安装包、理解前后端如何说话、并接入两种前端」的完整基础链路。后续章节会继续深入窗口、托盘、插件、安全等主题。