已掌握 Vue2 的开发者,快速上手 Vue3

发布于:2025-09-06 ⋅ 阅读:(14) ⋅ 点赞:(0)

对于已掌握 Vue2 的开发者,快速上手 Vue3 的核心是 聚焦「差异点」和「新增核心特性」,无需重复学习基础概念(如组件、指令、路由联动等)。以下是按「优先级+实用性」排序的核心知识点,附带 Vue2 对比和实战代码示例:

一、最核心变化:从 Options API 到 Composition API

Vue2 用 Options API(data、methods、computed 等选项)组织代码,逻辑分散在不同选项中;Vue3 新增的 Composition API(基于 setup 函数)允许按「业务逻辑」聚合代码,更适合复杂组件。

1.1 入口函数:setup()

setup 是 Composition API 的「入口」,替代了 Vue2 中 datacreatedbeforeCreate 的核心功能:

  • 执行时机:组件实例创建前(beforeCreate 之前),因此 setup没有 this(直接用 this 会报错)。
  • 返回值:返回的对象会暴露给模板(类似 Vue2 的 data+methods)。

1.2 响应式 API:替代 Vue2 的 data

Vue2 靠 Object.defineProperty 实现响应式,有「数组索引修改不响应」「对象新增属性不响应」的痛点;Vue3 用 Proxy 重写响应式,并用 ref/reactive 两个 API 声明响应式数据,彻底解决痛点。

场景 Vue2 写法 Vue3 写法 关键说明
基本类型(数字/字符串) data() { return { num: 0 } } const num = ref(0) ref 用于「基本类型」,访问时需加 .value(模板中不用加)
引用类型(对象/数组) data() { return { obj: { name: 'a' } } } const obj = reactive({ name: 'a' }) reactive 用于「引用类型」,直接访问属性(无需 .value
实战示例:响应式数据+方法
<!-- Vue3 组件 -->
<template>
  <div>
    <p>基本类型:{{ num }}</p>
    <p>引用类型:{{ obj.name }}</p>
    <button @click="addNum">加1</button>
    <button @click="changeName">改名字</button>
  </div>
</template>

<script setup>
// 1. 按需引入响应式 API(Vue3 推荐「树摇」,减少打包体积)
import { ref, reactive } from 'vue'

// 2. 声明响应式数据
const num = ref(0) // 基本类型用 ref
const obj = reactive({ name: 'Vue2' }) // 引用类型用 reactive

// 3. 声明方法(直接写函数,无需嵌套在 methods 中)
const addNum = () => {
  num.value += 1 // ref 类型在 JS 中需加 .value
}

const changeName = () => {
  obj.name = 'Vue3' // reactive 类型直接修改属性
}
</script>

1.3 计算属性与监听:computed/watch

替代 Vue2 的 computedwatch 选项,用法更灵活(可在 setup 内随时声明)。

(1)计算属性 computed
<script setup>
import { ref, computed } from 'vue'

const num = ref(0)
// 只读计算属性(默认)
const doubleNum = computed(() => num.value * 2)

// 可写计算属性(需传对象)
const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (val) => {
    const [f, l] = val.split(' ')
    firstName.value = f
    lastName.value = l
  }
})
</script>
(2)监听器 watch

支持监听单个/多个响应式数据,功能比 Vue2 更强大:

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

const num = ref(0)
const obj = reactive({ name: 'a', age: 18 })

// 1. 监听 ref 数据
watch(num, (newVal, oldVal) => {
  console.log('num变了:', newVal, oldVal)
})

// 2. 监听 reactive 数据的单个属性(需用函数返回)
watch(() => obj.name, (newName) => {
  console.log('名字变了:', newName)
})

// 3. 监听多个数据(数组形式)
watch([num, () => obj.age], ([newNum, newAge], [oldNum, oldAge]) => {
  console.log('num或age变了', newNum, newAge)
})
</script>

二、生命周期钩子的变化

Vue3 保留了 Vue2 的生命周期逻辑,但 钩子函数需按需引入,且部分名称有调整(去掉 before/after,统一用 onXxx)。

Vue2 生命周期 Vue3 对应钩子(需引入) 说明
beforeCreate 无(直接用 setup setup 执行时机更早
created 无(直接用 setup 同上
beforeMount onBeforeMount 组件挂载前
mounted onMounted 组件挂载后(常用)
beforeUpdate onBeforeUpdate 数据更新前
updated onUpdated 数据更新后
beforeDestroy onBeforeUnmount 组件卸载前(名称调整)
destroyed onUnmounted 组件卸载后(常用,名称调整)
实战示例:组件挂载后请求数据
<script setup>
import { onMounted } from 'vue'
import axios from 'axios'

// 组件挂载后请求数据(替代 Vue2 的 mounted 选项)
onMounted(async () => {
  const res = await axios.get('/api/data')
  console.log('请求结果:', res.data)
})
</script>

三、模板语法的 2 个关键变化

Vue3 模板支持更多灵活写法,核心变化集中在「多根节点」和「v-model 统一」。

3.1 多根节点(Fragment)

Vue2 模板 必须有一个根节点(否则报错);Vue3 支持「多根节点」,无需外层包裹 div

<!-- Vue3 合法模板(无需根节点) -->
<template>
  <p>第一个节点</p>
  <p>第二个节点</p>
</template>

3.2 v-model 统一(替代 sync 修饰符)

Vue2 中,v-modelvalue+input 事件的语法糖,syncupdate:prop 事件的语法糖,两者需区分;Vue3 统一了 v-model,直接通过「参数」绑定任意属性,彻底替代 sync

场景 Vue2 写法 Vue3 写法
基础双向绑定 <Child v-model="num" /> <Child v-model="num" />
自定义属性绑定(sync) <Child :title.sync="title" /> <Child v-model:title="title" />
实战示例:自定义输入框组件
<!-- 父组件 -->
<template>
  <CustomInput 
    v-model="num"          <!-- 基础绑定(默认绑定 value 属性) -->
    v-model:title="title"  <!-- 自定义绑定(绑定 title 属性) -->
  />
</template>

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

const num = ref(0)
const title = ref('Vue3')
</script>

<!-- 子组件 CustomInput.vue -->
<template>
  <input 
    :value="modelValue"  <!-- 基础绑定的默认属性名:modelValue(替代 Vue2 的 value) -->
    @input="$emit('update:modelValue', $event.target.value)"  <!-- 触发更新 -->
    
    :value="title"       <!-- 自定义绑定的属性名:title -->
    @input="$emit('update:title', $event.target.value)"       <!-- 触发更新 -->
  />
</template>

<script setup>
// 子组件需声明接收的属性(替代 Vue2 的 props 选项)
defineProps(['modelValue', 'title'])
// 子组件需声明可触发的事件(可选,用于类型提示)
defineEmits(['update:modelValue', 'update:title'])
</script>

四、全局 API 的变化(createApp

Vue2 用 new Vue() 创建全局实例,Vue3 用 createApp 替代,避免全局污染,用法更严谨。

操作 Vue2 写法 Vue3 写法
创建全局实例 new Vue({ el: '#app', render: h => h(App) }) createApp(App).mount('#app')
全局挂载组件 Vue.component('MyBtn', MyBtn) app.component('MyBtn', MyBtn)
全局挂载指令 Vue.directive('focus', { ... }) app.directive('focus', { ... })
实战示例:main.js 入口文件
// Vue2 main.js
import Vue from 'vue'
import App from './App.vue'

Vue.component('MyBtn', MyBtn) // 全局组件
new Vue({ render: h => h(App) }).$mount('#app')

// Vue3 main.js(推荐用 <script setup>,但入口文件需显式创建 app)
import { createApp } from 'vue'
import App from './App.vue'
import MyBtn from './MyBtn.vue'

// 1. 创建 app 实例
const app = createApp(App)
// 2. 全局配置(组件、指令、原型链等)
app.component('MyBtn', MyBtn) // 全局组件
// 3. 挂载到 DOM
app.mount('#app')

五、必学新增特性(提升开发效率)

5.1 异步组件:defineAsyncComponent

Vue2 异步组件需用 () => import(),Vue3 用 defineAsyncComponent 封装,支持更灵活的加载逻辑(如加载失败、加载中状态):

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

// 1. 基础异步组件(替代 Vue2 的 () => import('./Child.vue'))
const Child = defineAsyncComponent(() => import('./Child.vue'))

// 2. 带加载状态的异步组件
const AsyncChild = defineAsyncComponent({
  loader: () => import('./AsyncChild.vue'),
  loadingComponent: Loading, // 加载中显示的组件
  errorComponent: Error,     // 加载失败显示的组件
  delay: 200,                // 延迟 200ms 后显示加载组件(避免闪烁)
})
</script>

5.2 传送门:Teleport(解决样式嵌套问题)

Teleport 允许将组件的 DOM 渲染到任意位置(如 body 下),避免被父组件样式(如 overflow: hidden)影响,常用於模态框、弹窗。

<template>
  <button @click="showModal = true">打开弹窗</button>
  
  <!-- Teleport:将内容渲染到 body 下 -->
  <Teleport to="body">
    <div class="modal" v-if="showModal">
      <p>弹窗内容(渲染在 body 下,不受父组件样式影响)</p>
      <button @click="showModal = false">关闭</button>
    </div>
  </Teleport>
</template>

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

六、快速上手步骤总结

  1. 放弃 this:用 setup 作为入口,数据用 ref/reactive 声明,方法直接写函数。
  2. 替换生命周期:按需求引入 onMounted/onUnmounted 等钩子,替代 Vue2 的选项。
  3. 统一 v-model:用 v-model:prop 替代 sync,子组件通过 update:prop 触发更新。
  4. 调整全局 API:入口文件用 createApp 创建实例,全局组件/指令用 app.xxx 挂载。
  5. 按需用新特性:异步组件用 defineAsyncComponent,弹窗用 Teleport

通过以上知识点,你可以直接将 Vue2 项目的核心逻辑迁移到 Vue3,剩余细节(如 provide/inject 增强、script setup 语法糖进阶)可在实战中逐步补充。


网站公告

今日签到

点亮在社区的每一天
去签到