Skip to content

Vue 3 完整教程

Vue 3 是一个渐进式 JavaScript 框架,用于构建用户界面。本教程将带您从基础到进阶,全面掌握 Vue 3 的核心概念和最佳实践。

什么是 Vue 3?

Vue 3 是 Vue.js 的最新主要版本,带来了许多重要的改进和新特性:

  • 🚀 更好的性能 - 更小的包体积,更快的渲染速度
  • 🔧 Composition API - 更灵活的逻辑复用方式
  • 📦 更好的 TypeScript 支持 - 原生 TypeScript 支持
  • 🌳 Tree-shaking 友好 - 按需引入,减少包体积

环境准备

安装 Node.js

确保您的系统已安装 Node.js 16+ 版本:

bash
node --version
npm --version

创建 Vue 3 项目

使用 Vite 创建新项目(推荐):

bash
npm create vue@latest my-vue-app
cd my-vue-app
npm install
npm run dev

或使用 Vue CLI:

bash
npm install -g @vue/cli
vue create my-vue-app
cd my-vue-app
npm run serve

基础概念

1. 模板语法

Vue 使用基于 HTML 的模板语法:

vue
<template>
  <div>
    <!-- 文本插值 -->
    <h1>{{ title }}</h1>
    
    <!-- 属性绑定 -->
    <img :src="imageUrl" :alt="imageAlt">
    
    <!-- 事件监听 -->
    <button @click="handleClick">点击我</button>
    
    <!-- 条件渲染 -->
    <p v-if="isVisible">这段文字是可见的</p>
    
    <!-- 列表渲染 -->
    <ul>
      <li v-for="item in items" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

2. 响应式数据

使用 refreactive 创建响应式数据:

vue
<script setup>
import { ref, reactive } from 'vue'

// 基本类型使用 ref
const count = ref(0)
const message = ref('Hello Vue 3!')

// 对象类型使用 reactive
const user = reactive({
  name: '张三',
  age: 25,
  email: 'zhangsan@example.com'
})

// 修改数据
const increment = () => {
  count.value++
}

const updateUser = () => {
  user.name = '李四'
  user.age = 30
}
</script>

3. 计算属性

使用 computed 创建计算属性:

vue
<script setup>
import { ref, computed } from 'vue'

const firstName = ref('张')
const lastName = ref('三')

// 只读计算属性
const fullName = computed(() => {
  return firstName.value + lastName.value
})

// 可写计算属性
const fullNameWritable = computed({
  get() {
    return firstName.value + lastName.value
  },
  set(newValue) {
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})
</script>

4. 侦听器

使用 watchwatchEffect 侦听数据变化:

vue
<script setup>
import { ref, watch, watchEffect } from 'vue'

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

// 侦听单个数据源
watch(count, (newValue, oldValue) => {
  console.log(`count 从 ${oldValue} 变为 ${newValue}`)
})

// 侦听多个数据源
watch([count, () => user.name], ([newCount, newName], [oldCount, oldName]) => {
  console.log('count 或 user.name 发生了变化')
})

// 立即执行的侦听器
watchEffect(() => {
  console.log(`当前 count: ${count.value}`)
})
</script>

组件开发

1. 组件定义

vue
<!-- UserCard.vue -->
<template>
  <div class="user-card">
    <img :src="user.avatar" :alt="user.name">
    <h3>{{ user.name }}</h3>
    <p>{{ user.email }}</p>
    <button @click="$emit('follow', user.id)">关注</button>
  </div>
</template>

<script setup>
// 定义 props
const props = defineProps({
  user: {
    type: Object,
    required: true
  }
})

// 定义 emits
const emit = defineEmits(['follow'])
</script>

<style scoped>
.user-card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 16px;
  text-align: center;
}
</style>

2. 组件使用

vue
<template>
  <div>
    <UserCard 
      v-for="user in users" 
      :key="user.id"
      :user="user"
      @follow="handleFollow"
    />
  </div>
</template>

<script setup>
import UserCard from './components/UserCard.vue'

const users = ref([
  { id: 1, name: '张三', email: 'zhangsan@example.com', avatar: '/avatar1.svg' },
  { id: 2, name: '李四', email: 'lisi@example.com', avatar: '/avatar2.svg' }
])

const handleFollow = (userId) => {
  console.log(`关注用户 ${userId}`)
}
</script>

3. 插槽 (Slots)

vue
<!-- Card.vue -->
<template>
  <div class="card">
    <header class="card-header">
      <slot name="header"></slot>
    </header>
    <main class="card-content">
      <slot></slot>
    </main>
    <footer class="card-footer">
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

使用插槽:

vue
<template>
  <Card>
    <template #header>
      <h2>卡片标题</h2>
    </template>
    
    <p>这是卡片的主要内容</p>
    
    <template #footer>
      <button>确定</button>
      <button>取消</button>
    </template>
  </Card>
</template>

状态管理

使用 Pinia

安装 Pinia:

bash
npm install pinia

创建 store:

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

export const useUserStore = defineStore('user', () => {
  const user = ref(null)
  const isLoggedIn = computed(() => !!user.value)
  
  const login = async (credentials) => {
    // 登录逻辑
    const response = await api.login(credentials)
    user.value = response.data
  }
  
  const logout = () => {
    user.value = null
  }
  
  return {
    user,
    isLoggedIn,
    login,
    logout
  }
})

在组件中使用:

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

const userStore = useUserStore()

const handleLogin = async () => {
  await userStore.login({
    username: 'admin',
    password: '123456'
  })
}
</script>

路由管理

使用 Vue Router

安装 Vue Router:

bash
npm install vue-router@4

配置路由:

javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '/user/:id', component: User, props: true }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

在组件中使用:

vue
<template>
  <nav>
    <router-link to="/">首页</router-link>
    <router-link to="/about">关于</router-link>
  </nav>
  <router-view />
</template>

<script setup>
import { useRouter, useRoute } from 'vue-router'

const router = useRouter()
const route = useRoute()

const goToUser = (userId) => {
  router.push(`/user/${userId}`)
}
</script>

最佳实践

1. 组件设计原则

  • 单一职责:每个组件只负责一个功能
  • 可复用性:设计通用的组件接口
  • 可测试性:编写单元测试

2. 性能优化

vue
<script setup>
import { defineAsyncComponent } from 'vue'

// 异步组件
const AsyncComponent = defineAsyncComponent(() => 
  import('./components/HeavyComponent.vue')
)

// 使用 shallowRef 优化大型对象
import { shallowRef } from 'vue'
const largeData = shallowRef({})
</script>

3. 代码组织

src/
├── components/          # 通用组件
│   ├── ui/             # UI 组件
│   └── business/       # 业务组件
├── views/              # 页面组件
├── stores/             # 状态管理
├── composables/        # 组合式函数
├── utils/              # 工具函数
└── assets/             # 静态资源

常见问题

Q: 什么时候使用 ref,什么时候使用 reactive?

A:

  • 基本类型(string、number、boolean)使用 ref
  • 对象和数组使用 reactive
  • 需要重新赋值整个对象时使用 ref

Q: 如何在 Vue 3 中使用 TypeScript?

A:

vue
<script setup lang="ts">
interface User {
  id: number
  name: string
  email: string
}

const user = ref<User>({
  id: 1,
  name: '张三',
  email: 'zhangsan@example.com'
})
</script>

Q: 如何优化大列表渲染?

A: 使用虚拟滚动或分页,避免一次性渲染大量 DOM 元素。

总结

Vue 3 提供了强大而灵活的开发体验,通过 Composition API 和改进的性能,让我们能够构建更好的应用程序。掌握这些核心概念和最佳实践,您就能够高效地开发 Vue 3 应用。


继续学习:

vitepress开发指南