Vue2 & Vue3 知识构图

7 阅读2分钟

Vue 2 vs Vue 3 详细知识构图

一、核心架构差异

1. 响应式系统

特性Vue 2Vue 3
实现方式Object.defineProperty()Proxy
限制不能监测对象属性添加/删除完整拦截对象操作
数组监听需要特殊处理自动支持
性能初始化时遍历所有属性懒代理,按需拦截
深层对象递归定义getter/setter仅在访问时代理

2. 组件API风格

Vue 2: Options API (选项式)
  ├─ data()
  ├─ computed
  ├─ methods
  ├─ watch
  ├─ lifecycle hooks
  └─ 代码分散在不同选项中

Vue 3: Composition API (组合式) ✓ 推荐
  ├─ setup()
  ├─ ref() / reactive()
  ├─ computed()
  ├─ watch()
  ├─ 生命周期hooks
  └─ 代码按功能逻辑组织

二、语法对比速查表

创建应用

Vue 2:

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})

Vue 3:

createApp(App).mount('#app')

数据响应式

Vue 2:

export default {
  data() {
    return {
      count: 0,
      user: { name: 'Tom' }
    }
  }
}

Vue 3 (Composition API):

import { ref, reactive } from 'vue'

export default {
  setup() {
    const count = ref(0)           // 基础类型用ref
    const user = reactive({        // 对象用reactive
      name: 'Tom'
    })
    return { count, user }
  }
}

计算属性

Vue 2:

computed: {
  fullName() {
    return this.firstName + this.lastName
  }
}

Vue 3:

import { computed } from 'vue'

const fullName = computed(() =>
  firstName.value + lastName.value
)

方法

Vue 2:

methods: {
  handleClick() {
    this.count++
  }
}

Vue 3:

const handleClick = () => {
  count.value++
}

监听器

Vue 2:

watch: {
  count(newVal, oldVal) {
    console.log('count changed:', newVal)
  },
  'user.name': {
    handler(newVal) { },
    deep: true
  }
}

Vue 3:

import { watch } from 'vue'

watch(count, (newVal, oldVal) => {
  console.log('count changed:', newVal)
})

watch(() => user.name, (newVal) => { })

// watchEffect (自动追踪依赖)
watchEffect(() => {
  console.log(count.value)  // 依赖自动收集
})

生命周期钩子

Vue 2Vue 3
beforeCreate无 (用setup代替)
created无 (用setup代替)
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
errorCapturedonErrorCaptured

使用方式:

// Vue 2
export default {
  mounted() { }
}

// Vue 3
import { onMounted } from 'vue'
onMounted(() => { })

三、模板语法

v-model

Vue 2 (组件):

// 子组件
props: ['value'],
methods: {
  handleChange(val) {
    this.$emit('input', val)
  }
}

// 父组件
<MyInput v-model="count" />

Vue 3:

// 子组件
defineProps(['modelValue'])
defineEmits(['update:modelValue'])

// 父组件
<MyInput v-model="count" />
// 等同于
<MyInput :modelValue="count" @update:modelValue="count = $event" />

// 多个v-model
<MyInput v-model:title="title" v-model:content="content" />

动态组件

Vue 2:

<component :is="currentComponent" />

Vue 3:

<Suspense>
  <component :is="currentComponent" />
  <template #fallback>
    Loading...
  </template>
</Suspense>

Slots (插槽)

Vue 2:

<!-- 父组件 -->
<MyComponent>
  <template slot="header">Header</template>
  <template slot="default">Content</template>
</MyComponent>

<!-- 子组件 -->
<slot name="header"></slot>
<slot></slot>

Vue 3:

<!-- 父组件 -->
<MyComponent>
  <template #header>Header</template>
  <template #default>Content</template>
</MyComponent>

<!-- 子组件 -->
<slot name="header"></slot>
<slot></slot>

四、组件通信

Props & Emits

Vue 2:

props: {
  count: {
    type: Number,
    required: true,
    default: 0
  }
},
methods: {
  handleClick() {
    this.$emit('update', this.count + 1)
  }
}

Vue 3:

const props = defineProps({
  count: {
    type: Number,
    default: 0
  }
})

const emit = defineEmits(['update'])

const handleClick = () => {
  emit('update', props.count + 1)
}

上下文 Context

Vue 2:

methods: {
  handleClick() {
    this.$parent.count++
    this.$root.globalMethod()
    this.$slots
    this.$scopedSlots
  }
}

Vue 3:

import { getCurrentInstance } from 'vue'

const instance = getCurrentInstance()
// instance.parent
// instance.root
// instance.slots
// instance.emit

五、常用特性对比

Provide / Inject

Vue 2:

// 父组件
provide: {
  count: this.count
}

// 子组件
inject: ['count']

Vue 3:

import { provide, inject } from 'vue'

// 父组件
provide('count', ref(0))

// 子组件
const count = inject('count')

自定义指令

Vue 2:

directives: {
  focus: {
    bind(el) { el.focus() },
    update(el) { }
  }
}

Vue 3:

const vFocus = {
  mounted(el) { el.focus() },
  updated(el) { }
}

// 使用
<input v-focus />

混入 Mixins

Vue 2:

const myMixin = {
  data() { return { msg: 'hello' } },
  methods: { hello() {} }
}

export default {
  mixins: [myMixin]
}

Vue 3 (推荐 Composable):

// 可组合函数
export function useMyComposable() {
  const msg = ref('hello')
  const hello = () => {}
  return { msg, hello }
}

export default {
  setup() {
    const { msg, hello } = useMyComposable()
    return { msg, hello }
  }
}

六、性能优化

动态导入

Vue 2:

components: {
  MyComponent: () => import('./MyComponent.vue')
}

Vue 3:

import { defineAsyncComponent } from 'vue'

const MyComponent = defineAsyncComponent(
  () => import('./MyComponent.vue')
)

性能改进

  • ⚡ Proxy响应式更快
  • ⚡ Tree-shaking支持,包体积更小
  • ⚡ 虚拟滚动更优化
  • ⚡ 编译器性能提升

七、学习策略

Vue 2Vue 3 迁移路线
├─ 第一步:理解Composition API
│  ├─ ref vs reactive
│  ├─ computed vs watch
│  └─ 生命周期钩子
├─ 第二步:掌握新特性
│  ├─ defineProps/defineEmits
│  ├─ defineExpose
│  └─ 脚本语法糖 (<script setup>)
└─ 第三步:重构项目
   ├─ Mixins → Composables
   ├─ Options API → Composition API
   └─ 迁移状态管理

八、快速记忆要点

Vue 2Vue 3记忆点
this.dataref.valueref需要.value
computed: {}computed(fn)计算属性变函数
watch: {}watch(dep, fn)监听变显式化
methods: {}const fn = () => {}方法变常规函数
beforeCreate/createdsetup()声明周期提前
$emit('event')emit('event')事件需显式声明