vue3相比vue2到底改变了啥(vue3新增了哪些新特性)

vue3出来有一段时间了,可能还有很大一部分小伙伴们对vue3还处于一个朦胧的状态,不知道到底相比vue2,到底有哪些改变。在使用上,又有哪些不同。那么,今天,我们就来说叨说叨,vue3相比vue2,到底做了哪些改变

vue3做了哪些改变

1、源码

  1. vue3源码组织方式,由vue2的flow改成了vue3的typescript
  2. vue3移除了一些不常用的api,如inline-template,filter。
  3. 部分模块改成了按需引入,对Tree-shaking的支持更好,tree-shaking可以使模块按需引入,如keep-alive, transition, v-model等都会变成按需引入。

2、使用上

  1. 新增了composition API(组合API),原来vue2中的optionsAPI依然可以使用。即:vue3中同时兼容compositionAPI 和 optionsAPI。
    优点:一个基于函数的API。将同一功能逻辑的代码集合到一起。优化了之前项目大时,同一功能的逻辑代码分散的问题。可以更灵活的组织组件的逻辑

    • 有人可能会说了,啥是optionsAPI,我们vue2中通过在data, computed, watch, methods 中定义属性和方法,来共同处理页面逻辑的这种方式就是optionsAPI。也就是我们正常使用vue2做项目用的就是optionsAPI,这种api的写法,让我们实现同一功能的代码,可能分散在不同的地方,不易于查找
    • compositionAPI侧重于将同一功能的代码,都封装在同一个函数中,比如变量的定义,变量的使用等等,都在一起,然后最终,在setup中调用。
      vue3相比vue2到底改变了啥(vue3新增了哪些新特性)_第1张图片
  2. 新增3个响应式函数,reactive, toRefs, ref

    • reactive作用是将引用类型的数据转化为响应式数据(可监测的数据,响应式数据发生变化会触发页面重新渲染)
      vue3相比vue2到底改变了啥(vue3新增了哪些新特性)_第2张图片
      上图,相当于创建一个响应式dog对象,如果不加reactive,那么当dog绑定在dom上时,dog对象发生变化时,视图是不会更新的。

    • toRefs作用是将一个响应式对象的所有属性的值也转化为一个响应式对象,(即,toRefs的参数必须是一个响应式对象)这样,当把属性解构出来使用时,解构出来的变量也会是响应式对象,这个响应式对象都存在一个value属性,原本的属性值就放在这个value下面
      在这里插入图片描述
      如上图,dog是响应式对象,我们通过解构的方式,解构出color, type两个变量,那么,假设我们把color, type这两个变量也绑定在模板上,比如:
      在这里插入图片描述
      那么,当color和type的值发生变化时,或者说dog.color, dog.type发生变化时,页面是不会更新的。因为解构出来的color和type并不是响应式的。此时,如果解构的时候我们加上toRefs,那么color,type也会变成响应式对象,它本质是一个对象,这个对象有个value属性,color的属性值是放在value下的,可以简单理解为 color = {value: ‘yellow’}, type = { value: ‘哈士奇’}。但是,color和type如果在模板上使用时,是可以直接使用的,不需要color.value,type.value。而在script中使用,就必须通过color.value, type.value才能获取到值

    • ref方法作用是将一个基本类型的数据转化为一个响应式对象,该对象也是存在value属性,基本数据类型的值存储在value属性中。如果ref参数传递了一个引用类型,那么ref内部会直接调用reactive去将这个对象转化为响应式对象
      在这里插入图片描述
      相当于创建一个变量count = 0. 本质count也是对象, 简单理解为count = {value: 0}

难听懂吗,没关系,具体的,我们下篇文章来详细说vue3的compositionAPI的使用,到时候会详细介绍reactive, toRefs, ref这3个函数

  1. 生命周期函数的变化
    因为vue3旨在将相关功能的代码写在一个函数中,那么有时候我们可能会写成一个公共模块(公共函数),然后导入到其他地方使用,那么这种情况下,我们就有必要在模块(函数)中去使用我们的生命周期,而这个函数的调用,最终是在setup中调用的,所以生命周期也可以说是写在setup中的。如果是在setup中使用生命周期函数,那么写法如下
    vue3相比vue2到底改变了啥(vue3新增了哪些新特性)_第3张图片
    首先,因为setup函数的调用是在beforeCreate和created之间调用,所以在setup中beforeCreate 和 created就没有存在的必要了,因为这两个生命周期中的代码,你都可以写在setup中
    其他生命周期的使用,基本都加了个on前缀。
    同时将destroyed改成了unmounted
    如果是在setup函数同级去使用生命周期,那就以左边图为准

3、性能方面

  1. 响应式系统升级 (defineProperty变更为proxy)

    • 响应式核心实现从通过Object.defineProperty变为proxy,解决了definProperty无法监听对象新增属性以及无法跟踪数组索引以及数组length的问题
      vue2中,当我们给一个对象新增一个属性时,如数组arr的每一项都是object,object原本没有name属性,此时我们通过循环arr,拿到每一项item 然后,item.name=‘张三’,新增一个name属性,那么视图是不会更新的,因为无法监听新增属性。
      同理,数组通过索引arr[2] = ‘fsdf’ 直接改变数组,或者arr.length = 0 这种方式直接改变数组,视图也是不会更新的,因为也监听不到。proxy解决了这些问题
  2. 编译优化

    • vue3中会标记和提升所有静态节点(没有绑定变量的节点),静态节点会在页面首次渲染时使用h函数创建一个vnode,vue3将这个创建过程提升到render函数外部。下一次再渲染时,这些静态节点不需要再重新生成vnode,而是直接复用之前创建好的
    • vue3中会对动态节点进行标记,通过patchflag对动态节点进行标记,比如dom只绑定的是动态text,则标记为1(实际标记值不一定是1,我这里只是举例),只绑定的是动态props属性,标记为8,同时绑定了动态props和text标记为9等。后续diff比较时,会通过这些标记来判断该比较哪些东西。假设发现patchflag为1,那么diff比较时,就只比较text属性就行了,避免了很多其他不必要的diff比较,从而提升diff速度
    • 缓存事件处理程序,绑定的事件,在渲染时,会创建一个函数,函数内就是我们绑定的函数的调用,vue3会将生成的这个函数缓存起来,下一次渲染时,直接取这个缓存的函数在这里插入图片描述
      如果,绑定了一个事件函数chooseLabel,在vue2中,转化为render函数时,该事件依然绑定的是这个函数,那么,当我们改变了这个绑定的函数时,假设改成了下图
      在这里插入图片描述
      那么事件绑定函数发生变化(绑定发生变化),是不是会触发diff的比较啊
      而,vue3中,在render函数中,是将事件处理函数放在了一个函数中去调用,并将这个函数缓存起来
      如下:
      在这里插入图片描述
      我们的事件处理函数,实际是在一个箭头函数中被调用,这样,当我们改变事件处理函数时,vue3中缓存的那个函数实际是没有改变的(即:绑定未发生变化),只是这个缓存函数内的执行代码发生了变化而已,故不会触发更新,避免了不必要的更新

vue3相比vue2的主要变化点,我们就说到这了,看完这篇文章,是会对vue3的新特性,有了一些了解呢。
后面我们会继续写两篇vue3的文章,一篇是compositionAPI的使用,重点讲解如果用vue3写项目。另一篇是vue3响应式核心原理解析,重点带大家认识vue3是如何进行数据监测的

你可能感兴趣的:(vue3,vue.js,vue3,reactive,ref,toRefs)