news 2026/4/20 11:49:28

Vue2和Vue3的对比

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue2和Vue3的对比

这里写目录标题

  • 一、Vue2和Vue3区别概览
  • 二、开发层表面差异:直观感知的功能变化
    • 1、API 风格:Options API vs Composition API
    • 2、模板语法:更灵活的渲染能力
    • 🔥 核心差异速查
      • 1. 根元素
      • 2. v-model
      • 3. v-if与v-for优先级
      • 4. 插槽语法
      • 5. 过滤器
      • 6. 事件修饰符
      • 7. 自定义指令
      • 8. 样式深度选择器
      • 变化示例
      • Vue 2 → Vue 3 示例
      • 性能优势
    • 3、生命周期钩子:调整与新增
      • 1. 钩子重命名(重要!)
      • 2. Composition API 新格式
      • 3 对照表
    • 4、 关键点
      • 1. setup() 替代两个钩子
      • 2. 执行顺序
      • 3. 使用建议
    • 5、总结
  • 三、 Vue 2 与 Vue 3 框架层核心代码差异
    • 1、 核心架构对比
    • 2、 底层实现重构详解
      • 1. 响应式系统重写
        • Vue 2:Object.defineProperty
        • Vue 3:Proxy
      • 2. 虚拟 DOM 优化
        • Vue 2:全量 Diff
        • Vue 3:编译时优化 + Patch Flag
      • 3. 编译器重构
        • Vue 2:运行时编译
        • Vue 3:编译时优化
      • 4. 源码架构重构
        • vue 2:Monolithic
        • Vue 3:Monorepo + 模块化
      • 5. TypeScript 全面支持
        • Vue 2:后期添加
        • Vue 3:原生支持
      • 6. 自定义渲染器
        • Vue 2:复杂实现
        • Vue 3:简化设计
    • 7、架构设计理念变化
      • 从 Options API 到 Composition API
      • 从运行时到编译时
    • 8、 总结
      • 1. 性能飞跃
      • 2. 开发体验
      • 3. 扩展性

Vue 3 代表了 Vue 框架的一次重大飞跃。它在性能、开发体验(特别是 Composition API 和 TS)、灵活性和功能上都带来了显著的提升。虽然 Composition API 需要一些时间适应,但其带来的逻辑组织、复用和维护性的优势对于构建现代、复杂的前端应用是至关重要的。对于新项目,Vue 3 是毋庸置疑的选择;对于老项目,应积极评估并规划向 Vue 3 的迁移,Vue2在2023年底已经停止维护。

一、Vue2和Vue3区别概览

特性Vue2Vue3
架构&响应式Options API(选项式API主导)Composition API(组合式API主导)+ Options API
响应式原理Object.defineProprety数据劫持Proxy数据代理
性能良好显著提升
构建工具Vue CLI(基于 Webpack)Vite
状态管理VueXPinia
TypeScript弱支持,需额外配置原生支持
Fragment单根节点限制支持多根节点
Tree-Shaking有限支持原生支持
Teleport内置 ()
Suspense内置
全局 APIVue 构造函数挂载,全局配置创建应用实例(createApp),避免全局污染
事件 API$on, $off, $once删除
v-model1个组件仅1个 v-model支持多个 v-model (带参数),组件双向绑定更灵活
指令钩子bind, inserted 等与组件生命周期对齐,命名和语义更一致

二、开发层表面差异:直观感知的功能变化

Vue2 与 Vue3 在日常开发中最直观的差异,集中在 API 风格、模板语法、生命周期等高频使用场景,这些变化直接影响开发效率与代码组织方式。

1、API 风格:Options API vs Composition API

这是 Vue2 与 Vue3 最核心的开发体验差异,决定了代码的组织逻辑。

特性Vue2(Options API)Vue3(Composition API + Options API)
代码组织方式按 “选项” 划分代码:将数据(data)、方法(methods)、计算属性(computed)等拆分到不同选项中,逻辑分散在多个选项里。按 “功能逻辑” 聚合代码:通过setup()函数或<script setup>语法,将同一业务逻辑(如表单验证、数据请求)的代码集中在一起,无需跨选项查找。
代码复用依赖 Mixins、Scoped Slots 实现,但存在命名冲突、逻辑来源不清晰等问题(如多个 Mixins 都定义了handleClick方法)。通过组合式函数(Composables)复用逻辑,如useRequest()、useForm(),逻辑来源明确,无命名冲突,可灵活组合。
TypeScript 支持需通过vue-class-component等第三方库间接支持,类型推导不完整,配置复杂。原生支持 TypeScript,setup()函数、响应式 API(ref/reactive)均能提供完整类型推导,无需额外配置。

代码示例对比:实现 “计数器 + 数据请求” 的简单功能

<!--Vue2(OptionsAPI):逻辑分散在多个选项--><template><div>{{count}}<button @click="add">+1</button></div><div>{{user.name}}</div></template><script>exportdefault{data(){return{count:0,user:{}// 类型无法自动推导}},methods:{add(){this.count++// 依赖this上下文,容易出现指向问题},fetchUser(){axios.get('/api/user').then(res=>{this.user=res.data})}},mounted(){this.fetchUser()// 生命周期与方法分离}}</script>
<!--Vue3(<script setup>+CompositionAPI):逻辑聚合--><template><div>{{count}}<button @click="add">+1</button></div><div>{{user.name}}</div></template><script setup lang="ts">import{ref,onMounted}from'vue'importaxiosfrom'axios'// 计数器逻辑(聚合)constcount=ref(0)// 明确的响应式变量,TypeScript自动推导为number类型constadd=()=>{count.value++// 直接操作变量,无this依赖}// 用户数据请求逻辑(聚合)constuser=ref<{name:string}>({name:''})// 显式定义类型constfetchUser=async()=>{constres=awaitaxios.get('/api/user')user.value=res.data}// 生命周期与逻辑绑定onMounted(fetchUser)</script>

2、模板语法:更灵活的渲染能力

Vue 3 模板更灵活、更强大、更简洁

🔥 核心差异速查

1. 根元素

  • Vue 2❌ 必须单根元素
  • Vue 3✅ 支持多根(Fragment)

2. v-model

  • Vue 2:单个v-model(触发input事件)
  • Vue 3:多个v-model:xxx(触发update:xxx事件)

3. v-if与v-for优先级

  • Vue 2v-for>v-if
  • Vue 3v-if>v-for

4. 插槽语法

  • Vue 2slot="name"slot-scope
  • Vue 3:统一v-slot:name(简写#name

5. 过滤器

  • Vue 2✅ 支持:{{ text | filter }}
  • Vue 3❌ 移除:用方法或计算属性替代

6. 事件修饰符

  • Vue 2:基本修饰符
  • Vue 3:新增.middle.right,移除按键码支持

7. 自定义指令

  • Vue 2bindinsertedupdate
  • Vue 3:对齐组件生命周期mountedupdated

8. 样式深度选择器

  • Vue 2>>>/deep/::v-deep
  • Vue 3:统一:deep():slotted():global()

变化示例

Vue 2 → Vue 3 示例

<!-- Vue 2 --><template><div><!-- 必须包裹 --><Childv-model="data"><templateslot="header">标题</template><p>{{ text | capitalize }}</p></Child></div></template><!-- Vue 3 --><template><Childv-model:data="data"><!-- 多根元素 --><template#header>标题</template><!-- 新插槽语法 --><p>{{ capitalize(text) }}</p><!-- 无过滤器 --></Child></template>
  1. 移除不必要的<div>包装
  2. 插槽语法slot#
  3. 过滤器改为方法调用
  4. 检查v-if/v-for逻辑
  5. 使用新的v-model语法

性能优势

  • 更小的包体积
  • 更好的Tree-shaking
  • 更快的渲染速度
  • 更少的内存占用

结论:Vue 3模板语法更现代化、更灵活,新项目应直接使用,老项目可逐步迁移。

3、生命周期钩子:调整与新增

1. 钩子重命名(重要!)

Vue 2 → Vue 3: beforeDestroy → beforeUnmount destroyed → unmounted

2. Composition API 新格式

// Vue 2(Options API)exportdefault{mounted(){/* ... */},destroyed(){/* ... */}}// Vue 3(Composition API)import{onMounted,onUnmounted}from'vue'setup(){onMounted(()=>{/* ... */})onUnmounted(()=>{/* ... */})}

3 对照表

Vue 2 钩子Vue 3 Options APIVue 3 Composition API
beforeCreate✅ 保留❌ 移除(用 setup())
created✅ 保留❌ 移除(用 setup())
beforeMount✅ 保留onBeforeMount
mounted✅ 保留onMounted
beforeUpdate✅ 保留onBeforeUpdate
updated✅ 保留onUpdated
beforeDestroybeforeUnmountonBeforeUnmount
destroyedunmountedonUnmounted
activated✅ 保留onActivated
deactivated✅ 保留onDeactivated
errorCaptured✅ 保留onErrorCaptured

4、 关键点

1. setup() 替代两个钩子

// Vue 2beforeCreate(){/* 组件初始化前 */}created(){/* 组件创建完成 */}// Vue 3setup(){/* 替代上面两个钩子 */}

2. 执行顺序

// 组件启动:setup()→ beforeMount → mounted// 组件销毁:beforeUnmount → unmounted

3. 使用建议

  • 新项目:用 Composition API (onXxx)
  • 老项目:先改名称 (destroyedunmounted)
  • 清理资源:在onUnmounted中清理定时器/监听器

5、总结

“销毁改卸载,组合API用on前缀,setup替代创建钩子”
关键变化:Vue3移除了beforeDestroy/destroyed,统一为beforeUnmount/unmounted,语义更准确;同时Composition API的钩子需从vue中导入,避免与Options API混淆。

三、 Vue 2 与 Vue 3 框架层核心代码差异

1、 核心架构对比

维度Vue 2Vue 3
源码组织单文件、Flow 类型模块化、TypeScript
响应式系统Object.definePropertyProxy
虚拟 DOM全量 DiffPatch Flag 优化 Diff
模板编译运行时编译编译时优化
源码体积完整打包模块化、Tree-shaking
性能指标基准参考快 1.3-2 倍

2、 底层实现重构详解

1. 响应式系统重写

Vue 2:Object.defineProperty
// 核心原理functiondefineReactive(obj,key,val){Object.defineProperty(obj,key,{enumerable:true,configurable:true,get(){// 依赖收集dep.depend()returnval},set(newVal){if(newVal===val)return// 触发更新val=newVal dep.notify()}})}// ❌ 局限:// 1. 无法检测对象新增/删除属性// 2. 数组变异需要拦截原型方法// 3. 需要 Vue.set/Vue.delete// 4. 递归遍历性能开销大
Vue 3:Proxy
// 核心原理functionreactive(obj){returnnewProxy(obj,{get(target,key,receiver){// 依赖收集track(target,key)returnReflect.get(target,key,receiver)},set(target,key,value,receiver){// 触发更新constresult=Reflect.set(target,key,value,receiver)trigger(target,key)returnresult},deleteProperty(target,key){// 支持删除属性constresult=Reflect.deleteProperty(target,key)trigger(target,key)returnresult}})}// ✅ 优势:// 1. 完整对象监听// 2. 更好的数组支持// 3. 支持 Map、Set// 4. 惰性代理(用到才监听)// 5. 性能更好

2. 虚拟 DOM 优化

Vue 2:全量 Diff
// 简单对比算法functionpatch(oldVNode,newVNode){// 全量比较所有属性if(oldVNode.tag!==newVNode.tag){// 替换整个节点}// 深度递归比较子节点updateChildren(oldVNode.children,newVNode.children)}// ❌ 问题:// 1. 不必要的递归// 2. 静态内容重复比对// 3. 组件更新粒度粗
Vue 3:编译时优化 + Patch Flag
// 编译时生成优化提示constvnode={type:'div',props:{id:'app',class:normalizeClass({active:isActive})},children:[{type:'h1',children:'静态标题',patchFlag:1},// 静态{type:'p',children:dynamicText,patchFlag:2},// 文本动态{type:'button',props:{onClick:handler},patchFlag:8// 只有事件变化}]}// Patch Flag 类型constPatchFlags={TEXT:1,// 动态文本CLASS:2,// 动态 classSTYLE:4,// 动态 stylePROPS:8,// 动态 props(不含 class/style)FULL_PROPS:16,// 动态 key 或其他HYDRATE_EVENTS:32}// ✅ 优化效果:// 1. 静态节点提升(只创建一次)// 2. 动态节点标记(只更新变化部分)// 3. 树结构打平(减少递归层级)// 4. 事件缓存(避免重复绑定)

3. 编译器重构

Vue 2:运行时编译
// 主要工作:// 1. 解析模板 → AST// 2. 优化静态节点// 3. 生成渲染函数(运行时)// 生成代码示例:functionrender(){with(this){return_c('div',{attrs:{id:'app'}},[_c('h1',[_v(_s(message))]),_c('button',{on:{click:onClick}},[_v('点击')])])}}// ❌ 问题:// 1. 运行时编译开销// 2. with 语句性能差// 3. 无法深度优化
Vue 3:编译时优化
// 主要优化:// 1. 模块化编译器(@vue/compiler-core)// 2. 源码映射(Source Map)// 3. 更好的错误提示// 4. Tree-shaking 支持// 生成的优化代码:import{createElementVNodeas_createElementVNode,toDisplayStringas_toDisplayString,openBlockas_openBlock,createElementBlockas_createElementBlock}from'vue'exportfunctionrender(_ctx,_cache){return(_openBlock(),_createElementBlock('div',{id:'app'},[// 静态节点提升到外部_hoisted_1,// 动态节点带 Patch Flag_createElementVNode('p',null,_toDisplayString(_ctx.message),1/* TEXT */)]))}// 静态节点提升到渲染函数外const_hoisted_1=/*#__PURE__*/_createElementVNode('h1',null,'静态标题',-1/* HOISTED */)

4. 源码架构重构

vue 2:Monolithic
vue/ ├── src/ │ ├── core/ # 核心 │ ├── compiler/ # 编译器 │ ├── platforms/ # 平台相关 │ └── shared/ # 共享代码 └── dist/ ├── vue.js # 完整版(带编译器) ├── vue.runtime.js # 运行时版 └── vue.min.js # 压缩版 // ❌ 问题: // 1. 代码耦合度高 // 2. Tree-shaking 困难 // 3. 维护成本高
Vue 3:Monorepo + 模块化
vue-next/ ├── packages/ │ ├── compiler-core/ # 编译核心 │ ├── compiler-dom/ # DOM 编译 │ ├── runtime-core/ # 运行时核心 │ ├── runtime-dom/ # DOM 运行时 │ ├── reactivity/ # 响应式系统 ← 可单独使用! │ ├── shared/ # 共享工具 │ └── vue/ # 主包(整合) └── scripts/ ├── build.js # 构建脚本 └── dev.js # 开发脚本 // ✅ 优势: // 1. 模块化设计 // 2. 更好的 Tree-shaking // 3. 响应式系统可独立使用 // 4. 更容易维护和扩展

5. TypeScript 全面支持

Vue 2:后期添加
// 需要额外的类型声明importVuefrom'vue'// 组件选项类型exportdefaultVue.extend({props:{msg:String},data(){return{count:0}}})// ❌ 问题:// 1. this 类型推导有限// 2. 装饰器语法复杂// 3. 与 Vue API 集成度低
Vue 3:原生支持
// 源码完全用 TypeScript 编写import{defineComponent,ref}from'vue'exportdefaultdefineComponent({props:{msg:{type:String,required:true}},setup(props){// 完美的类型推断constcount=ref(0)// props 类型安全console.log(props.msg.toUpperCase())return{count}}})// ✅ 优势:// 1. 源码即类型// 2. 更好的 IDE 支持// 3. Composition API 类型友好// 4. 减少运行时错误

6. 自定义渲染器

Vue 2:复杂实现
// 需要实现完整渲染接口classMyRenderer{createElement(){/* ... */}insert(){/* ... */}remove(){/* ... */}// ... 数十个方法}// 使用复杂Vue.createRenderer=function(){returnnewMyRenderer()}
Vue 3:简化设计
// 核心接口简化import{createRenderer}from'@vue/runtime-core'const{createApp}=createRenderer({patchProp,// 处理属性insert,// 插入节点remove,// 移除节点createElement,// 创建元素createText,// 创建文本createComment,// 创建注释setText,// 设置文本setElementText,// 设置元素文本parentNode,// 父节点nextSibling// 下一个兄弟节点})// 轻松支持多平台// - @vue/runtime-dom (Web)// - @vue/runtime-test (测试)// - @vue/runtime-canvas (Canvas)// - 自定义渲染器(如小程序、Native)

7、架构设计理念变化

从 Options API 到 Composition API

// Vue 2:基于选项的组织// 逻辑分散在 data、methods、computed 中exportdefault{data(){return{x:0,y:0}},mounted(){window.addEventListener('mousemove',this.update)},destroyed(){window.removeEventListener('mousemove',this.update)},methods:{update(e){this.x=e.x;this.y=e.y}}}// Vue 3:基于逻辑的组合// 相关逻辑组织在一起import{ref,onMounted,onUnmounted}from'vue'functionuseMouse(){constx=ref(0)consty=ref(0)constupdate=e=>{x.value=e.x;y.value=e.y}onMounted(()=>window.addEventListener('mousemove',update))onUnmounted(()=>window.removeEventListener('mousemove',update))return{x,y}}// 逻辑复用更自然exportdefault{setup(){const{x,y}=useMouse()return{x,y}}}

从运行时到编译时

// 编译时发现更多优化机会constCompilerOptimizations={静态提升:'将静态节点提到渲染函数外',树结构打平:'减少虚拟DOM层级',缓存事件处理器:'避免重复创建函数',PatchFlag标记:'只更新动态部分',内联函数:'减少函数调用开销'}

8、 总结

1. 性能飞跃

  • Proxy 响应式:性能更好,支持完整对象
  • 编译时优化:静态提升、Patch Flag
  • Tree-shaking:按需导入,包更小

2. 开发体验

  • TypeScript 原生支持:更好的类型推导
  • 组合式 API:逻辑复用更灵活
  • 模块化设计:维护和扩展更容易

3. 扩展性

  • 自定义渲染器:支持多平台
  • 独立响应式包:可单独使用
  • 渐进式升级:兼容 Vue 2 大部分 API

Vue 3 是一次彻底的重构,在保持 API 兼容性的同时,拥抱现代 JavaScript 特性,通过架构层面的优化实现了性能的质的飞跃。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 18:29:39

HDF5完整文件结构与操作指南

HDF5完整文件结构与操作指南 目录 完整文件结构概览基础数据集类型组结构操作属性系统高级数据类型引用和链接压缩和分块可扩展数据集维度标签完整示例代码 1. 完整文件结构概览 1.1 理想的HDF5文件结构 comprehensive_example.h5 # 根文件 │ ├── &…

作者头像 李华
网站建设 2026/4/18 3:25:29

【Java毕设源码分享】基于springboot+vue的高校社团管理系统设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/18 3:25:48

LLM应用实践: NoteBookLM初次使用

欢迎关注公众号&#xff1a;爱学习的妮妮qiang 1. 背景 上周发表了一篇《LLM应用剖析: 手机智能助理Phone Agent》&#xff0c;但跑通整个流程只是熟悉了工具的使用&#xff0c;因此需要知其然知其所以然。遂开启研读其论文《AutoGLM: Autonomous Foundation Agents for GUIs…

作者头像 李华
网站建设 2026/4/18 3:25:44

AWK:一行之诗,一门哲学,一种被遗忘的数据处理圣经

思维导图在这&#xff1a;https://www.anygraphanywhere.com/automap/mindmap.html?link1765772302518-1765772302518 在技术编年史的宏大叙事中&#xff0c;我们习惯于歌颂那些构建了操作系统、网页或人工智能的“全能语言”。然而&#xff0c;有一个寂静的角落&#xff0c;…

作者头像 李华
网站建设 2026/4/18 3:25:38

spdlog 库下载,编译,并使用的例子

文章目录一、下载 spdlog方法1&#xff1a;使用包管理器&#xff08;推荐&#xff09;方法2&#xff1a;手动下载二、编译 spdlog使用 CMake 编译编译选项三、在项目中使用CMake 项目集成简单使用示例四、编译示例程序五、依赖要求注意事项一、环境准备1. 安装编译工具2. 获取 …

作者头像 李华