vue2与vue3的区别

375 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

vue2与vue3的区别

  1. vue2支持的是选项式API,vue3同时支持选项式API和组合式API
  2. 响应是数据流实现原理不同
  3. vue3具有透传attribute的功能,在组件上使用class属性,回头传到该组件的模板上,自动添加到根元素的class属性身上。
  4. 在同一个标记上使用v-if和v-for,v-if会优先执行
  5. vue3中,v-if和v-else会自动添加不同的key,不会复用
  6. templace上使用v-for,key属性可以添加在templace元素上。
  7. vue3支持碎片(就是在组件可以拥有多个根节点)
  8. 建立data:vue2把数据放入data属性中。vue3使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
  9. 生命周期钩子 — Lifecyle Hooks
  10. 父子传参不同,setup()函数特性
  11. vue3 Teleport瞬移组件

具体解释

vue2支持的是选项式API,vue3同时支持选项式API和组合式API
  • 什么是选项式API什么是组合式API呢
    选项式API:在vue2项目中使用的就是选项式API
    选项式API的代码风格:data选项写数据,methods选项写函数等等,一个功能逻辑的分散。
    优点:易于学习和使用,写代码的位置已经约定好了。
    缺点:代码组织性差,相似的逻辑代码不便于复用,逻辑复杂代码多了不好阅读,虽然提供了mixins用来封装逻辑,但是出现数据函数覆盖的概率很大,不好维护。
    组合式API:在vue3中使用的就是组合API写法(当然也可以使用vue2中的选项式API写法)
    代码风格:一个功能逻辑的代码组织在一起(包括数据,函数等等)
    优点:功能逻辑复杂繁多情况下,各个功能逻辑代码组织在一起,便于阅读和维护。
    缺点:需要有良好的代码组织能力和拆分逻辑能力。
    选项式和组合式API的关系
  1. 组合式API的目的是增强,而不是取代选项式API,vue3对两种API都支持
  2. 简单的场景使用选项式API更加简单方便
  3. 需要强烈支持TS的项目首选组合式API
  4. 需要大量逻辑复用的场景首选组合式API

vue2与vue3响应数据流实现原理不同

vue2的响应数据流
vue2数据双向绑定是由数据劫持结合发布-订阅的模式实现的,通过object.defineProperty()来劫持对象属性的getter和setter操作,在数据变动时发布消息给订阅者,触发响应的监听回调。
通过object.defineProperty()这个方法接收3个参数,一个是定义属性的对象,第二个是要定义或者修改属性名,第三个是将被定义或者修改的属性描述符。

image.png
重要知识点

  • observer:数据监听器,监听数据对象进行遍历,包括子属性对象的属性上都加上getter和setter。
  • compile:解析模板指令,将模板中的遍历替换成数据,然后初始化渲染页面视图,并将每个指令对应节点绑定更新函数,添加监听数据的订阅者,一旦数据有变化,收到通知,更新视图。
  • watcher:订阅者是observer和compile之间的通信桥梁,在自身实例化时往消息订阅器dep里添加自己,自身必须有个update()方法,带属性变动dep.notice()通知时,能调用自身的update()方法,并触发compile中绑定的回调。
  • depend:消息订阅器,当有多个订阅者的时候,需要有一个统一维护者。depend用来收集订阅者,内部维护了一个数组。
详细分析
  1. 我们已经知道实现双向数据绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器observer,用来监听所有属性。
  2. 每个属性都会有一个订阅者watcher,如果一旦属性发生变化,就需要告诉订阅者watcher看是否需要更新
  3. 因为订阅者是有很多的,所以需要一个消息订阅器depend来专门手机这些订阅者,然后在监听器和订阅者之间进行统一管理。
  4. 接着还需要一个指令解析器compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者,并替换模板数据或者绑定相应的函数,从而更新视图。
    vue3的响应数据流
    因为vue2的object.defineProperty只能劫持对象属性,无法监控数组下标的变化,导致通过数据下标添加的元素不能实时响应的弊端,为了解决这个问题,经vue内部处理后,可以使用push()、pop()、shift()、unshift()、splice()、sort()、reverse()进行hack处理,所以其他数组属性也是检测不到,具有一定的局限性。
    因为object.defineProperty只能劫持对象属性,从而需要对每个对象的每个属性进行遍历。vue2里是通过递归+遍历data对象来实现对数据的监控的,如果属性值是对象的话,还需要深度遍历。
    而vue3中的proxy不仅可以dailduixiang,还可以代理数组,还可以代理动态添加的属性,有13中劫持操作。
    get获取每个key值(接收2个参数,目标值和目标值key值)
    set设置某个key值(目标值、目标的key值,要改变的值、改变前的原始值)
    apply使用in操作符判断某个key是否存在
    deleteProperty删除一个property
    definepRroperty定义一个新的property
    。。。。。。。。

透传Attribute

对于只有一个根元素的组件,当你使用了class attribute时,这是class会被添加到根元素上,并与该元素上已有的class合并。
例如,声明了一个组件名MyComponent子组件模板如下:

image.png
在父组件内调用该组件时添加一些class:

image.png
渲染出来的HTML为:

image.png
class的绑定也是同样的:

image.png
当isActive为真是,被渲染的组件是:

image.png
如果你的组件有多个根元素,需要指定那个根元素来接收这个class,可以通过组件的$attrs属性来实现指定:

image.png
被渲染为:

image.png
以上这些模式叫做透传attribute。

在同一个标记上使用v-if和v-for,v-if会优先执行

在vue3中同一个标记上使用v-if和v-for,v-if会优先执行,它的优先级比v-for高。
如果想同时写的话可以将v-for写在templace上。将要操作的DOM用templace包裹起来。

image.png
注意同时使用v-if和v-for是不推荐的,因为二者的优先级。如果不注意的话v-if的条件将无法访问到v-for作用域内定义的变量名。

setup

在vue3中,使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下散步来建立反应性数据:

  1. 从vue引入reactive
  2. 使用reactive()方法来声明我们的数据为响应性数据
  3. 使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据。

image.png

image.png

vue2与vue3的生命周期

image.png

  1. setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
  2. onBeforeMount() : 组件挂载到节点上之前执行的函数。
  3. onMounted() : 组件挂载完成后执行的函数。
  4. onBeforeUpdate(): 组件更新之前执行的函数。
  5. onUpdated(): 组件更新完成之后执行的函数。
  6. onBeforeUnmount(): 组件卸载之前执行的函数。
  7. onUnmounted(): 组件卸载完成后执行的函数
    若组件被keep-alive包含,则多出下面两个钩子函数。
  8. onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行 。
  9. onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。