速通Vue3:从入门到实战(附图解+对比)

针对Vue2转Vue3开发者 / 刚接触框架的新手,快速掌握核心差异与实战技巧


一、生命周期对比(Vue2 vs Vue3)

1.1 生命周期对照表(含组合式API)

vue2 是选项式 API的写法,vue3 是支持选项式和组合式两种写法,

建议大家都用组合式(见第十条):

Vue 2 生命周期Vue 3 选项式 APIVue 3 组合式 API解释
beforeCreatebeforeCreatesetup()在实例初始化之后,数据观测 data 和 event/watcher 事件配置之前被调用。此阶段无法访问 data 中的数据和 methods 中的方法。
createdcreatedsetup()实例已经创建完成之后被调用。在这一步,实例已经完成了数据观测 dataproperty 和 method 的计算、watch/event 事件回调。然而,挂载阶段还没有开始,$el 属性目前不可用。
beforeMountbeforeMountonBeforeMount在挂载开始之前被调用:相关的 render 函数首次被调用。此时模板还未挂载到页面上。
mountedmountedonMounted实例已经挂载之后调用。此时模板已经编译完成并挂载到页面上,可以访问 $el 元素。
beforeUpdatebeforeUpdateonBeforeUpdate在数据更新之前被调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updatedupdatedonUpdated由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。此时 DOM 已经更新,可以执行依赖于更新后的 DOM 的操作。
beforeDestroybeforeUnmountonBeforeUnmount在实例销毁之前调用。在这一步,实例仍然完全可用。在 Vue 3 中,“销毁” 概念改为 “卸载”。
destroyedunmountedonUnmounted在实例销毁之后调用。调用后,所有的事件监听器和子实例都已经被销毁。在 Vue 3 中对应实例卸载之后。

1.2 关键差异解析

钩子Vue2Vue3组合式API触发时机
setup()❌ 无✅ 核心入口组件初始化时立即执行,替代beforeCreate和created
onMountedmountedonMounted组件挂载完成后执行(可访问DOM)
onUnmounteddestroyedonUnmounted组件卸载后清理副作用

二、组件通信全方案(Vue3组合式API版)

2.1 父子组件通信(组合式API标准写法)

<!-- 父组件 Parent.vue -->
<template>
  <Child 
    :msg="parentMsg" 
    @update="handleUpdate"
  />
</template>

<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const parentMsg = ref('Hello Vue3!')
const handleUpdate = (newValue) => {
  parentMsg.value = newValue
}
</script>
<!-- 子组件 Child.vue -->
<template>
  <div>
    {{ msg }}
    <button @click="sendData">Update</button>
  </div>
</template>

<script setup>
// Vue3组合式API核心写法
const props = defineProps(['msg'])
const emit = defineEmits(['update'])

const sendData = () => {
  emit('update', 'New Value from Child')
}
</script>

2.2 新旧写法对比(表格版)

功能Vue2选项式APIVue3组合式API
定义propsprops: ['msg']defineProps(['msg'])
定义事件emits: ['update']defineEmits(['update'])
触发事件this.$emit('update', value)emit('update', value)
响应式数据data() { return { count: 0 } }const count = ref(0)

2.3 组合式API优势说明

<script setup>语法糖

  • 自动暴露顶层绑定

  • 无需return模板可用数据

  • 更简洁的API组织方式

defineProps/defineEmits

// 带类型提示的进阶写法
const props = defineProps({
  msg: {
    type: String,
    required: true
  }
})

const emit = defineEmits<{
  (e: 'update', value: string): void
}>()

模板直接访问

<!-- 无需.value直接访问 -->
<div>{{ msg }}</div>

<!-- 方法直接调用 -->
<button @click="sendData">Send</button>

2.4 其他通信方式补充

快速访问子组件实例(模板ref)

<!-- 父组件 -->
<template>
  <Child ref="childRef" />
  <button @click="childRef.someMethod()">调用子组件方法</button>
</template>

<script setup>
import { ref } from 'vue'
const childRef = ref(null)
</script>

依赖注入(provide/inject)

// 祖先组件
import { provide, ref } from 'vue'
const counter = ref(0)
provide('globalCounter', counter)

// 后代组件
import { inject } from 'vue'
const counter = inject('globalCounter')

2.5 插槽进阶用法

作用域插槽示例

<!-- 子组件 -->
<slot name="footer" :user="userData"></slot>

<!-- 父组件 -->
<template v-slot:footer="{ user }">
  <div>{{ user.name }}</div>
</template>

三、响应式系统核心

3.1 ref vs reactive 对比

特性refreactive
支持类型所有类型对象/数组
模板访问自动解包直接访问
重新赋值✅ 保持响应❌ 丢失响应
解构响应需.value访问需toRefs包裹

3.2 最佳实践选择

// 基本类型用ref
const count = ref(0)

// 复杂对象用reactive
const user = reactive({
  name: 'Alice',
  age: 25
})

// 函数返回用ref保持响应
const state = ref({
  data: null,
  loading: true
})

四、异步更新队列与 nextTick 原理

4.1 异步更新机制

Vue3 通过异步更新队列优化 DOM 更新性能,其核心逻辑如下:

  • 批量更新:数据变更时,Vue 不会立即更新 DOM,而是将变更推入队列,在下一个事件循环中批量执行17

  • 去重优化:同一数据的多次修改仅保留最终值,避免重复计算8

  • 执行时机:优先使用微任务(Promise/MutationObserver),降级为宏任务(setTimeout)

// 示例:多次修改仅触发一次更新
const count = ref(0)
count.value++  // 修改1
count.value++  // 修改2
// DOM 更新只执行一次

4.2 nextTick 核心作用

  • 获取最新 DOM:在数据变更后,通过 nextTick 确保回调在 DOM 更新后执行79

  • 实现原理:利用 Promise 微任务队列(优先级:Promise > MutationObserver > setTimeout)

import { nextTick } from 'vue'

async function updateData() {
  data.value = '新值'
  await nextTick()
  console.log('DOM已更新:', document.getElementById('element'))
}

五、Vuex 状态管理(Vue3 适配版)

5.1 核心概念对比

概念作用Vue3 特性
State全局状态存储支持 Composition API 访问
Mutations同步修改状态(原子操作)必须通过 commit 触发
Actions异步操作 + 提交 Mutations支持 async/await 语法
Getters计算属性派生类似组件的 computed

5.2 组合式 API 使用

// store.js
import { createStore } from 'vuex'

export default createStore({
  state: { user: null },
  mutations: {
    SET_USER(state, payload) {
      state.user = payload
    }
  },
  actions: {
    async fetchUser({ commit }) {
      const user = await api.getUser()
      commit('SET_USER', user)
    }
  }
})

// 组件中使用
import { useStore } from 'vuex'

setup() {
  const store = useStore()
  const user = computed(() => store.state.user)
  
  const login = async () => {
    await store.dispatch('fetchUser')
  }

  return { user, login }
}

六、Vue-Router 路由管理(Vue3 新版)

6.1 路由配置优化

// router.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    component: () => import('@/views/Home.vue'),  // 动态导入
    meta: { requiresAuth: true }
  },
  {
    path: '/about',
    component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue')
  }
]

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

 6.2 路由守卫升级

// 全局前置守卫
router.beforeEach((to, from) => {
  if (to.meta.requiresAuth && !store.state.user) {
    return '/login'
  }
})

// 组合式 API 中使用
import { onBeforeRouteLeave } from 'vue-router'

setup() {
  onBeforeRouteLeave((to, from) => {
    // 离开路由前的逻辑
  })
}

七、Vue3 Diff算法优化

7.1 核心优化点图解

7.2 性能提升场景

  • 列表头尾插入效率提升50%

  • 大数据量列表渲染优化30%

  • 静态节点标记跳过比对


八、综合性能优化策略

8.1 异步组件 + 路由懒加载

// 异步组件定义
const AsyncComp = defineAsyncComponent(() => import('./Component.vue'))

// 路由配置
{ path: '/dashboard', component: () => import('@/views/Dashboard.vue') }

 8.2 Keep-alive 缓存策略

<router-view v-slot="{ Component }">
  <keep-alive include="Home,About">
    <component :is="Component" />
  </keep-alive>
</router-view>

8.3 状态管理优化

  • 使用 Pinia(Vuex 的替代方案)简化状态管理

  • 模块化拆分 Store,避免单一文件过大


九、常见问题解决方案

9.1 DOM 操作时机问题

// 错误示例
data.value = '新值'
document.getElementById('element').textContent = data.value  // 可能获取旧 DOM

// 正确方案
data.value = '新值'
nextTick(() => {
  document.getElementById('element').textContent = data.value
})

 9.2 路由参数监听

import { watch } from 'vue'
import { useRoute } from 'vue-router'

setup() {
  const route = useRoute()
  
  watch(
    () => route.params.id,
    (newId) => {
      fetchData(newId)
    }
  )
}

十、Vue3新特性速览

10.1 Composition API 优势

// 更灵活的逻辑组织
export default {
  setup() {
    const count = ref(0)
    
    // 可复用的逻辑片段
    const { data } = useFetch('/api/data')
    
    // 生命周期聚合
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    return { count, data }
  }
}

10.2 其他重要更新

特性Vue2Vue3改进
响应式系统Object.definePropertyProxy实现
模板指令v-for优先级高于v-ifv-if优先级高于v-for
Fragment组件❌ 不支持✅ 支持多根节点
Teleport组件❌ 无✅ 跨DOM层级传送内容

十一、TypeScript支持

11.1 类型声明示例

interface User {
  id: number
  name: string
}

const user = reactive<User>({
  id: 1,
  name: 'Alice'
})

11.2 组合式API类型推断

// 带类型提示的ref
const count = ref<number>(0)

// 类型安全的emit
const emit = defineEmits<{
  (e: 'update', value: number): void
}>()

十二、生态工具链(官方工具推荐)

工具用途命令示例
Vite极速开发环境npm create vite@latest
Pinia新一代状态管理npm install pinia
VueUse常用工具集合npm install @vueuse/core
Vitest单元测试框架npm install -D vitest

学习路线建议:先掌握组合式API -> 熟悉响应式原理 -> 实践常用生态工具 -> 深入性能优化技巧

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值