前言:Vue 3 自发布以来,凭借卓越的性能、对 TypeScript 的完美支持以及革命性的 Composition API,已成为现代前端开发的首选框架之一。本文将结合构建工具、状态管理和组件库生态,带你系统掌握 Vue 3 的核心概念与最佳实践。


目录

  1. 为什么选择 Vue 3?
  2. 核心语法:<script setup> 与响应式系统
  3. 逻辑复用:Composables 模式
  4. 状态管理:Pinia 实战
  5. 工程化:Vite 构建工具详解
  6. UI 生态:Naive UI 与其他组件库
  7. 国际化与多语言支持
  8. 最佳实践与常见陷阱
  9. 总结与学习路线

1. 为什么选择 Vue 3?

Vue 3 不仅仅是 Vue 2 的升级版本,它是一次架构层面的革新:

核心优势

  • 性能提升:基于 Proxy 的响应式系统,更快的渲染速度和更小的打包体积。
  • TypeScript 原生支持:所有源码用 TS 编写,提供极佳的类型推断。
  • Composition API:解决复杂组件逻辑复用的终极方案。
  • 更好的 Tree-shaking:按需引入,未使用的功能会被自动剔除。
  • 新特性:Teleport(传送门)、Suspense(异步组件)、Fragment(多根节点)等。

API 风格选择

Vue 3 支持两种 API 风格:

  • Options API(选项式):Vue 2 经典写法,适合简单组件。
  • Composition API(组合式):Vue 3 推荐写法,适合复杂逻辑和 TypeScript 项目。

建议:新项目一律使用 Composition API + <script setup>


2. 核心语法:<script setup> 与响应式系统

2.1 <script setup> 语法糖

<script setup> 是 Vue 3.2+ 推荐的编译时语法糖,让代码更简洁、性能更好。

特点

  • 自动暴露变量给模板,无需 return
  • 自动注册导入的组件。
  • 默认使用 Composition API。
  • 更好的 TypeScript 支持。
<script setup>
import { ref, computed } from 'vue'
import ChildComponent from './ChildComponent.vue'

// 直接定义,自动暴露
const count = ref(0)
const double = computed(() => count.value * 2)

function increment() {
  count.value++
}
// 不需要 return,ChildComponent 自动可用
</script>

<template>
  <ChildComponent />
  <button @click="increment">{{ count }} - {{ double }}</button>
</template>

2.2 响应式系统:ref vs reactive

Vue 3 提供了两个核心函数来创建响应式数据:

ref - 适用于任意类型
import { ref } from 'vue'

const count = ref(0)           // 基本类型
const user = ref({ name: '张三' }) // 对象

// JS 中访问需要 .value
count.value++
user.value.name = '李四'

// 模板中自动解包,无需 .value
// {{ count }} {{ user.name }}
reactive - 仅适用于对象/数组
import { reactive } from 'vue'

const state = reactive({
  count: 0,
  user: { name: '张三' }
})

// 直接访问,无需 .value
state.count++
state.user.name = '李四'

// ⚠️ 陷阱:不能直接替换整个对象
// state = { count: 1 } ❌ 会丢失响应性
最佳实践:统一使用 ref

社区趋势是优先使用 ref,因为:

  • 统一的心智模型(所有响应式数据都是 ref)。
  • 避免 reactive 的解构陷阱。
  • 更方便替换整个对象。
// ✅ 推荐写法
const count = ref(0)
const user = ref({ name: '张三' })

// 修改
count.value++
user.value = { name: '新名字' } // 可以直接替换

2.3 解构响应式对象:toRefs

直接解构 reactiveref 对象会丢失响应性,需要使用 toRefs

import { ref, toRefs } from 'vue'

const user = ref({ name: '张三', age: 18 })

// ❌ 错误:丢失响应性
// const { name } = user

// ✅ 正确:保持响应性
const { name, age } = toRefs(user)

// 现在 name.value 和 age.value 依然与 user 同步
name.value = '李四' // user.value.name 也会变

3. 逻辑复用:Composables 模式

Composables(组合式函数)是 Vue 3 逻辑复用的核心模式,替代了 Vue 2 的 Mixins。

3.1 什么是 Composables?

  • use 开头的函数(如 useMouse, useFetch)。
  • 内部使用 Composition API(ref, computed, 生命周期等)。
  • 返回响应式数据和方法供组件使用。

3.2 实战示例:useMouse

// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)

  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  return { x, y }
}
<!-- 组件中使用 -->
<script setup>
import { useMouse } from '@/composables/useMouse'

const { x, y } = useMouse()
</script>

<template>
  <div>鼠标位置:{{ x }}, {{ y }}</div>
</template>

3.3 Composables + Pinia 黄金模式

在复杂业务中,Composables 负责逻辑编排,Pinia 负责全局状态

// composables/useAuth.js
import { useUserStore } from '@/stores/user'
import { useRouter } from 'vue-router'
import { ref } from 'vue'

export function useAuth() {
  const userStore = useUserStore()
  const router = useRouter()
  const isLoading = ref(false)
  const error = ref(null)

  async function login(credentials) {
    isLoading.value = true
    try {
      const res = await api.login(credentials)
      userStore.setUser(res.data) // 更新 Pinia Store
      router.push('/dashboard')
    } catch (e) {
      error.value = e.message
    } finally {
      isLoading.value = false
    }
  }

  return { isLoading, error, login }
}

4. 状态管理:Pinia 实战

Pinia 是 Vue 官方推荐的状态管理库,替代 Vuex,更轻量、更简单、TS 支持更好。

4.1 核心概念

  • Store:状态容器,每个 Store 独立。
  • State:响应式数据(类似 data)。
  • Getters:计算属性(类似 computed)。
  • Actions:方法(支持异步,无 mutations)。

4.2 定义 Store

// stores/user.js
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useUserStore = defineStore('user', () => {
  // State
  const user = ref(null)
  const token = ref('')

  // Getters
  const isLoggedIn = computed(() => !!token.value)

  // Actions
  function setUser(newUser, newToken) {
    user.value = newUser
    token.value = newToken
  }

  function logout() {
    user.value = null
    token.value = ''
  }

  return { user, token, isLoggedIn, setUser, logout }
})

4.3 在组件中使用

<script setup>
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia'

const userStore = useUserStore()

// ✅ 推荐:使用 storeToRefs 解构,保持响应性
const { user, isLoggedIn } = storeToRefs(userStore)

// 直接调用 actions
function handleLogout() {
  userStore.logout()
}
</script>

5. 工程化:Vite 构建工具详解

Vite 是 Vue 3 的标配构建工具,提供极速的开发体验。

5.1 Vite vs Webpack

特性 Vite Webpack
开发启动 瞬时(利用浏览器 ESM) 慢(需打包)
热更新 毫秒级(与项目大小无关) 随项目增大变慢
生产构建 Rollup 自身
配置复杂度

5.2 核心机制

依赖预构建(Dependency Pre-Bundling)
  • 时机:首次启动或依赖变化时。
  • 工具:esbuild(Go 语言,极快)。
  • 目的:将 CommonJS/UMD 依赖转为 ESM,合并小文件。
  • 缓存位置node_modules/.vite/deps
热模块替换(HMR)
  • 通过 WebSocket 推送更新。
  • 仅重新编译修改的文件。
  • 注入运行时代码(/@vite/client)处理更新。

5.3 常用命令

npm run dev      # 开发服务器
npm run build    # 生产构建
npm run preview  # 预览生产构建(重要!)

重要:上线前务必运行 build && preview,验证路由刷新、资源路径等问题。


6. UI 生态:Naive UI 与其他组件库

6.1 Naive UI:Vue 3 + TS 的首选

Naive UI 是一个完全用 TypeScript 编写的 Vue 3 组件库,特点:

  • 完美的类型推断:原生 TS 编写,智能提示极佳。
  • 按需引入:Tree-shaking 友好,体积极小。
  • 主题定制:强大的主题配置系统,轻松实现深色模式。
  • 组件丰富:90+ 高质量组件,包括复杂的 Table、Tree、Cascader。
<script setup>
import { NButton, NMessageProvider, useMessage } from 'naive-ui'

const message = useMessage()
</script>

<template>
  <NMessageProvider>
    <NButton type="primary" @click="message.success('Hello!')">
      点击我
    </NButton>
  </NMessageProvider>
</template>

6.2 其他优秀组件库

  • Element Plus:Element UI 的 Vue 3 版本,生态成熟。
  • Ant Design Vue:企业级设计语言,组件丰富。
  • Vuetify:Material Design 风格。

7. 国际化与多语言支持

使用 vue-i18n 实现多语言支持:

7.1 安装与配置

npm install vue-i18n@9
// i18n.js
import { createI18n } from 'vue-i18n'

export default createI18n({
  legacy: false, // 启用 Composition API 模式
  locale: 'zh',
  messages: {
    zh: { welcome: '欢迎' },
    en: { welcome: 'Welcome' }
  }
})

7.2 在组件中使用

<script setup>
import { useI18n } from 'vue-i18n'

const { t, locale } = useI18n()

function switchLang() {
  locale.value = locale.value === 'zh' ? 'en' : 'zh'
}
</script>

<template>
  <h1>{{ t('welcome') }}</h1>
  <button @click="switchLang">切换语言</button>
</template>

8. 最佳实践与常见陷阱

8.1 最佳实践清单

  1. 始终使用 <script setup>
  2. 优先使用 ref,避免 reactive 的陷阱。
  3. 逻辑复用用 Composables,全局状态用 Pinia。
  4. 解构响应式对象必用 toRefsstoreToRefs
  5. 上线前必须 build && preview
  6. TypeScript 项目中选择 Naive UI 等 TS 友好库
  7. 不要提交 node_modules/.vite 到 Git

8.2 常见陷阱

陷阱 1:解构丢失响应性
// ❌ 错误
const { name } = reactive({ name: '张三' })

// ✅ 正确
const { name } = toRefs(reactive({ name: '张三' }))
陷阱 2:reactive 对象被替换
const state = reactive({ count: 0 })

// ❌ 错误:切断响应式连接
state = { count: 1 }

// ✅ 正确
Object.assign(state, { count: 1 })
// 或者直接用 ref
陷阱 3:忘记 .value
const count = ref(0)

// ❌ 错误
count++ 

// ✅ 正确
count.value++
陷阱 4:路由刷新 404
  • 原因:History 模式需要服务器配置 fallback。
  • 解决:使用 vite preview 测试,生产环境配置 Nginx/Apache 重定向。

9. 总结与学习路线

核心技术栈

Vue 3 + Vite + Pinia + Composables + TypeScript + Naive UI

学习路线建议

  1. 基础阶段(1-2 周)

    • 掌握 <script setup> 语法。
    • 理解 ref/reactive/computed/watch
    • 学会使用 toRefs 解构。
  2. 进阶阶段(2-3 周)

    • 编写 Composables 复用逻辑。
    • 使用 Pinia 管理全局状态。
    • 掌握 Vue Router 4。
  3. 工程化阶段(1-2 周)

    • 深入理解 Vite 原理(预构建、HMR)。
    • 配置 TypeScript、ESLint、Prettier。
    • 学习单元测试(Vitest + Testing Library)。
  4. 实战阶段(持续)

    • 选择一个 UI 库(推荐 Naive UI)。
    • 实现国际化(vue-i18n)。
    • 部署项目(Vercel/Netlify/Docker)。

推荐资源


结语:Vue 3 不仅仅是一个框架的升级,它代表了一种更现代化、更灵活的前端开发范式。掌握 Composition API、Composables 和 Pinia,你将能够构建出更高效、更可维护的大型应用。开始动手实践吧,最好的学习方式就是写代码!

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐