从vue2和vue3的区别聊起

前端面试中,最常见的问题是:"vue2和vue3有那些区别?"

今天,从这个问题开始,逐步梳理Web前端知识点。

区别1:响应式原理不同

Vue2 用 defineProperty,Vue3 用 Proxy

区别2:代码编写不同

Vue3 用 setup(),Vue2 用 data/methods

区别3:根节点数量不同

Vue2只能由1个根节点,Vue3可以有多个根节点

区别4:生命周期不同

Vue3合并了beforeUnmounted和beforeDestroy,合并了Unmounted和destory。

区别5:编译时 + 虚拟 DOM 的运行时优化

接下来来看下每个区别到底是怎么回事。

区别1:响应式原理不同

Vue2 用的是 Object.defineProperty,它通过代理对象的已有属性,在对属性进行get和set的时候,进行响应式操作。这个对属性的代理必须保证属性是已有的,所以临时添加一个属性,是没有被代理的,自然也就无法进行响应式。而删除一个属性,不会触发get和set,自然也没有响应式。而且删除属性后,属性被彻底移除,再操作这个属性,相当于新增属性,也不会触发响应式。

javascript 复制代码
const o = {}; // 创建一个新对象

// 通过 defineProperty 使用访问器属性描述符添加对象属性的示例
let bValue = 38;
Object.defineProperty(o, "b", {
  get() {
    return bValue;
  },
  set(newValue) {
    bValue = newValue;
    console.log("set o.b")
  },
});

// 对b赋值时,触发set
o.b = 42

// 输出
// set o.b

// 新增一个属性,无输出
o.c = 1
//无输出

对于数组的响应式,理论上每个下标也是一个特殊的数字属性,但是,数组通常变化频繁,且经常会创建稀疏数组,这样一来,对不一定用到的下标索引全部加上响应式代理,很明显是造成了性能的浪费,所以Vue2重写了数组原型上的push、pop、shift、unshift、splice、sort、reverse,这七个数组的操作方法,方法内部手动触发依赖更新。

Vue3 用的是Proxy,它通过代理对象本身来进行响应式操作,每次调用get/set时,都会传入相应的对象和属性名,这样可以在get/set内部进行对象属性的访问,从而精准的触发每个属性的响应式。而数组的下标索引也是特殊属性,所以也会触发set。从而一举解决Vue2中数组下标赋值不能响应式的问题。

javascript 复制代码
const o = {b: 38}; // 创建一个新对象

// 通过Proxy代理o

const newO = new Proxy(o, {
    get(obj, prop) {
        return obj[prop]
    },
    set(obj, prop, value) {
        obj[prop] = value
        console.log("set o." + prop)
        return ture;
    },
})

newO.b = 42 // 输出:set o.b

newO.c = 1 // 输出: set o.c


// 数组响应式
const a = [0, 1, 2];

const newA = new Proxy(a, {
    get(obj, prop) {
        return obj[prop]
    },
    set(obj, prop, value) {
        obj[prop] = value
        console.log("set a[" + prop + "]")
        return true;
    },
})


newA[0] = 1 // 输出:set a[0]
newA.length = 4 // 输出:set a[length]
newA[3] = 5 // 输出:set a[3]
console.log(a) // 输出[1,1,2,5]

"注意:Proxy 的 set trap 必须返回 true,否则在严格模式或调用数组原生方法时会抛出 TypeError。"

区别2:代码编写不同

Vue2主要使用选项式写法,通过data、props、methods、watch、computed等选项来组织代码,而Vue3可以用setup(),通过组合式写法,将代码按业务逻辑组合在一起,更符合业务代码编写的习惯。

在复杂组件中,一个业务功能(如'用户搜索+筛选+分页')往往涉及 data、methods、watch、computed 多个选项,代码被横向切割 ,阅读和维护成本高。而组合式 API 允许我们将同一逻辑关注点的代码放在一起,甚至封装成可复用的自定义 Hook(如 useUserSearch()),大幅提升内聚性和复用性。

区别3:根节点数量不同

Vue2只能由1个根节点,Vue3可以有多个根节点。这主要是因为Vue2 的虚拟 DOM diff 算法依赖唯一根。而 Vue3 引入了 Fragment(片段) ,内部能处理多个根节点,让模板更灵活,避免无意义的 <div> 包裹。而Fragment只存在于虚拟Dom中,是一层逻辑上的包裹,并不会渲染到真实Dom中。

区别4:生命周期不同

|-------------------|---------------------|
| Vue2 | Vue3 |
| beforeCreate | setup之前 |
| created | setup中 |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |

Vue3 对生命周期钩子进行了命名优化和逻辑整合

  • 将 Vue2 的 beforeDestroy 重命名为 onBeforeUnmount
  • 将 destroyed 重命名为 onUnmounted

同时,在组合式 API 中,所有生命周期钩子都以函数形式导入(如 onMounted, onUnmounted),并在setup() 中显式调用,使得生命周期逻辑可以按关注点与业务代码组织在一起,而不是分散在选项中。

区别5:编译与渲染性能优化机制不同

Vue3 在编译阶段对模板进行深度静态分析,并引入多项运行时优化:

  • PatchFlags(补丁标记):为每个虚拟节点标记动态部分(如文本、props),使 diff 时只关注变化内容;
  • Block Tree(区块树):将模板划分为独立区块,更新时仅追踪动态子树,跳过静态区域;
  • 静态提升(Hoisting):将纯静态节点提取到渲染函数外部,只创建一次,后续直接复用;
  • 事件处理器缓存:自动缓存内联函数,避免因引用变化导致子组件不必要更新。

这些优化使得 Vue3 的虚拟 DOM 更新性能显著优于 Vue2,尤其在大型组件中效果明显。

相关推荐
来杯三花豆奶2 小时前
Vue 2 中 Store (Vuex) 从入门到精通
前端·javascript·vue.js
老华带你飞2 小时前
个人网盘管理|基于springboot + vue个人网盘管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
刘一说2 小时前
Vue单页应用(SPA)开发全解析:从原理到最佳实践
前端·javascript·vue.js
疯狂成瘾者2 小时前
前端vue核心知识点
前端·javascript·vue.js
章豪Mrrey nical10 小时前
前后端分离工作详解Detailed Explanation of Frontend-Backend Separation Work
后端·前端框架·状态模式
我是小路路呀11 小时前
element级联选择器:已选中一个二级节点,随后又点击了一个一级节点(仅浏览,未确认选择),此时下拉框失去焦点并关闭
javascript·vue.js·elementui
JIngJaneIL12 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
澄江静如练_12 小时前
列表渲染(v-for)
前端·javascript·vue.js
Loo国昌13 小时前
Vue 3 前端工程化:架构、核心原理与生产实践
前端·vue.js·架构