现代 Vue 全栈开发实战:Vue 3.5 + TypeScript + Vite 7 + Tailwind CSS v4 + shadcn-vue + TanStack Query
引言:拥抱现代化 Vue 生态
随着 Vue 3.5、Vite 7 和 Tailwind CSS v4 的发布,Vue 生态迎来了新一轮的性能与开发体验提升。shadcn-vue
提供了精美的 UI 组件,而 TanStack Query
(原 React Query)则为 Vue 带来了强大的数据获取与状态管理能力。
在 Nidalee 项目中,我们整合了这套全栈技术栈,实现了高性能、类型安全、美观且易于维护的桌面应用。本文将以“主题系统”为例,带你从零搭建一个现代化 Vue 项目,涵盖项目初始化、核心配置和关键代码实现。
技术选型概览
- Vue 3.5: 最新的 Vue 核心,带来更好的性能和新特性。
- TypeScript: 提供静态类型检查,增强代码健壮性。
- Vite 7: 极速的构建工具,提供开箱即用的热更新。
- Tailwind CSS v4: 下一代 CSS 框架,配置驱动,原子化 CSS。
- shadcn-vue: 基于 Radix UI 和 Tailwind CSS 的高质量 Vue 组件库。
- TanStack Query (Vue): 强大的异步状态管理库,简化数据获取、缓存和更新。
1. 项目初始化
首先,使用 pnpm
(或你偏好的包管理器)创建一个新项目:
# 创建 Vite 项目
pnpm create vite@latest my-vue-app --template vue-ts
cd my-vue-app
# 安装依赖
pnpm install
# 安装 Tailwind CSS v4
pnpm add -D tailwindcss@next @tailwindcss/vite
# 初始化 Tailwind CSS
npx tailwindcss init -p
2. 配置 Tailwind CSS v4
Tailwind CSS v4 采用了全新的配置方式。编辑 tailwind.config.js
:
// tailwind.config.js
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
然后在 src/style.css
中引入 Tailwind:
/* src/style.css */
@import 'tailwindcss';
3. 配置 Vite 7 与 TypeScript
编辑 vite.config.ts
以启用 Tailwind 插件和 TypeScript 支持:
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
vue(),
tailwindcss(),
],
})
确保 tsconfig.json
正确配置了路径映射和模块解析:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
}
4. 集成 shadcn-vue
安装 shadcn-vue
及其依赖:
pnpm add shadcn-vue lucide-vue-next class-variance-authority clsx tailwind-merge
初始化 shadcn-vue
:
npx shadcn-vue@latest init
这会生成一个 components.json
配置文件,并在 src/components
下创建 ui
目录。你可以通过 CLI 添加组件,例如按钮:
npx shadcn-vue@latest add button
5. 集成 TanStack Query (Vue)
安装 @tanstack/vue-query
:
pnpm add @tanstack/vue-query
在 src/main.ts
中配置插件:
// src/main.ts
import { createApp } from 'vue'
import { VueQueryPlugin, QueryClient } from '@tanstack/vue-query'
import App from './App.vue'
import './style.css'
const app = createApp(App)
const queryClient = new QueryClient()
app.use(VueQueryPlugin, { queryClient })
app.mount('#app')
6. 实战:构建主题系统
我们将构建一个简单的主题系统,允许用户在浅色和深色模式之间切换,并动态改变主题色。
6.1. 主题状态管理
使用 Pinia 来管理主题状态。首先安装 Pinia:
pnpm add pinia
创建一个 store src/stores/themeStore.ts
:
// src/stores/themeStore.ts
import { defineStore } from 'pinia'
import { ref, watch } from 'vue'
export const useThemeStore = defineStore('theme', () => {
const isDark = ref(false)
const primaryColor = ref('#3b82f6') // 默认蓝色
// 监听主题变化并应用到 DOM
watch(isDark, (newVal) => {
if (newVal) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
}, { immediate: true })
// 监听主色变化并更新 CSS 变量
watch(primaryColor, (newVal) => {
document.documentElement.style.setProperty('--color-primary', newVal)
}, { immediate: true })
function toggleDark() {
isDark.value = !isDark.value
}
function setPrimaryColor(color: string) {
primaryColor.value = color
}
return { isDark, primaryColor, toggleDark, setPrimaryColor }
})
6.2. 应用根组件
在 src/App.vue
中使用 store 并提供切换功能:
<!-- src/App.vue -->
<script setup lang="ts">
import { useThemeStore } from '@/stores/themeStore'
import { Button } from '@/components/ui/button'
const themeStore = useThemeStore()
</script>
<template>
<div id="app" class="min-h-screen bg-background text-foreground flex flex-col items-center justify-center gap-4">
<h1 class="text-3xl font-bold">Modern Vue App</h1>
<p class="text-muted-foreground">Built with Vue 3.5, Vite 7, Tailwind CSS v4, shadcn-vue, and TanStack Query</p>
<div class="flex gap-2">
<Button @click="themeStore.toggleDark">
切换 {{ themeStore.isDark ? '浅色' : '深色' }} 模式
</Button>
<Button @click="themeStore.setPrimaryColor('#ef4444')" variant="outline">
红色主题
</Button>
<Button @click="themeStore.setPrimaryColor('#10b981')" variant="outline">
绿色主题
</Button>
</div>
<div class="mt-8 p-4 bg-card text-card-foreground rounded-lg shadow-sm border">
<p>这是一个卡片组件,展示了 shadcn-vue 的样式。</p>
</div>
</div>
</template>
6.3. Tailwind CSS 配置
为了让主题切换和颜色自定义生效,我们需要在 src/style.css
中定义 CSS 变量,并在 Tailwind 配置中引用它们:
/* src/style.css */
@import 'tailwindcss';
@theme {
--radius: 0.5rem;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-border: var(--border);
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--primary: var(--color-primary); /* 使用动态变量 */
--primary-foreground: 0 0% 98%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--border: 240 5.9% 90%;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--primary: var(--color-primary); /* 使用动态变量 */
--primary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--border: 240 3.7% 15.9%;
}
}
body {
background-color: hsl(var(--background));
color: hsl(var(--foreground));
margin: 0;
}
#app {
min-height: 100vh;
}
6.4. 使用 TanStack Query 获取数据
假设我们需要从一个 API 获取主题配置。我们可以创建一个 composable 来封装查询逻辑:
// src/composables/useThemeConfig.ts
import { useQuery } from '@tanstack/vue-query'
interface ThemeConfig {
defaultDarkMode: boolean
defaultPrimaryColor: string
}
const fetchThemeConfig = async (): Promise<ThemeConfig> => {
// 模拟 API 调用
return new Promise((resolve) => {
setTimeout(() => {
resolve({
defaultDarkMode: false,
defaultPrimaryColor: '#3b82f6'
})
}, 1000)
})
}
export const useThemeConfig = () => {
return useQuery({
queryKey: ['themeConfig'],
queryFn: fetchThemeConfig,
staleTime: 1000 * 60 * 5, // 5分钟
})
}
然后在 App.vue
中使用它来初始化默认主题:
<!-- src/App.vue (部分代码) -->
<script setup lang="ts">
import { useThemeStore } from '@/stores/themeStore'
import { useThemeConfig } from '@/composables/useThemeConfig'
import { Button } from '@/components/ui/button'
import { watch } from 'vue'
const themeStore = useThemeStore()
const { data: themeConfig, isLoading } = useThemeConfig()
// 当配置加载完成后,应用默认设置
watch(themeConfig, (config) => {
if (config) {
themeStore.isDark = config.defaultDarkMode
themeStore.setPrimaryColor(config.defaultPrimaryColor)
}
})
</script>
<template>
<div id="app" class="min-h-screen bg-background text-foreground flex flex-col items-center justify-center gap-4">
<div v-if="isLoading" class="text-muted-foreground">
加载主题配置中...
</div>
<template v-else>
<h1 class="text-3xl font-bold">Modern Vue App</h1>
<p class="text-muted-foreground">Built with Vue 3.5, Vite 7, Tailwind CSS v4, shadcn-vue, and TanStack Query</p>
<div class="flex gap-2">
<Button @click="themeStore.toggleDark">
切换 {{ themeStore.isDark ? '浅色' : '深色' }} 模式
</Button>
<Button @click="themeStore.setPrimaryColor('#ef4444')" variant="outline">
红色主题
</Button>
<Button @click="themeStore.setPrimaryColor('#10b981')" variant="outline">
绿色主题
</Button>
</div>
<div class="mt-8 p-4 bg-card text-card-foreground rounded-lg shadow-sm border">
<p>这是一个卡片组件,展示了 shadcn-vue 的样式。</p>
</div>
</template>
</div>
</template>
7. 总结
通过整合 Vue 3.5、TypeScript、Vite 7、Tailwind CSS v4、shadcn-vue 和 TanStack Query,我们构建了一个现代化、高性能且易于维护的前端应用。这套技术栈不仅提供了卓越的开发体验,还确保了最终产品的质量和性能。
“主题系统”的实现展示了如何将这些技术协同工作:Tailwind CSS v4 的原子化和配置驱动特性让样式管理变得简单;shadcn-vue 提供了美观且一致的 UI 组件;TanStack Query 简化了复杂的数据获取逻辑;而 Pinia 则优雅地管理了全局状态。
这套组合拳为现代 Vue 应用开发提供了一个坚实的起点,无论你是构建企业级应用还是个人项目,都能从中受益。