持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
vue2与vue3的区别
- vue2支持的是选项式API,vue3同时支持选项式API和组合式API
- 响应是数据流实现原理不同
- vue3具有透传attribute的功能,在组件上使用class属性,回头传到该组件的模板上,自动添加到根元素的class属性身上。
- 在同一个标记上使用v-if和v-for,v-if会优先执行
- vue3中,v-if和v-else会自动添加不同的key,不会复用
- templace上使用v-for,key属性可以添加在templace元素上。
- vue3支持碎片(就是在组件可以拥有多个根节点)
- 建立data:vue2把数据放入data属性中。vue3使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
- 生命周期钩子 — Lifecyle Hooks
- 父子传参不同,setup()函数特性
- vue3 Teleport瞬移组件
具体解释
vue2支持的是选项式API,vue3同时支持选项式API和组合式API
- 什么是选项式API什么是组合式API呢?
选项式API:在vue2项目中使用的就是选项式API
选项式API的代码风格:data选项写数据,methods选项写函数等等,一个功能逻辑的分散。
优点:易于学习和使用,写代码的位置已经约定好了。
缺点:代码组织性差,相似的逻辑代码不便于复用,逻辑复杂代码多了不好阅读,虽然提供了mixins用来封装逻辑,但是出现数据函数覆盖的概率很大,不好维护。
组合式API:在vue3中使用的就是组合API写法(当然也可以使用vue2中的选项式API写法)
代码风格:一个功能逻辑的代码组织在一起(包括数据,函数等等)
优点:功能逻辑复杂繁多情况下,各个功能逻辑代码组织在一起,便于阅读和维护。
缺点:需要有良好的代码组织能力和拆分逻辑能力。
选项式和组合式API的关系:
- 组合式API的目的是增强,而不是取代选项式API,vue3对两种API都支持
- 简单的场景使用选项式API更加简单方便
- 需要强烈支持TS的项目首选组合式API
- 需要大量逻辑复用的场景首选组合式API
vue2与vue3响应数据流实现原理不同
vue2的响应数据流
vue2数据双向绑定是由数据劫持结合发布-订阅的模式实现的,通过object.defineProperty()来劫持对象属性的getter和setter操作,在数据变动时发布消息给订阅者,触发响应的监听回调。
通过object.defineProperty()这个方法接收3个参数,一个是定义属性的对象,第二个是要定义或者修改属性名,第三个是将被定义或者修改的属性描述符。
重要知识点
- observer:数据监听器,监听数据对象进行遍历,包括子属性对象的属性上都加上getter和setter。
- compile:解析模板指令,将模板中的遍历替换成数据,然后初始化渲染页面视图,并将每个指令对应节点绑定更新函数,添加监听数据的订阅者,一旦数据有变化,收到通知,更新视图。
- watcher:订阅者是observer和compile之间的通信桥梁,在自身实例化时往消息订阅器dep里添加自己,自身必须有个update()方法,带属性变动dep.notice()通知时,能调用自身的update()方法,并触发compile中绑定的回调。
- depend:消息订阅器,当有多个订阅者的时候,需要有一个统一维护者。depend用来收集订阅者,内部维护了一个数组。
详细分析
- 我们已经知道实现双向数据绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器observer,用来监听所有属性。
- 每个属性都会有一个订阅者watcher,如果一旦属性发生变化,就需要告诉订阅者watcher看是否需要更新
- 因为订阅者是有很多的,所以需要一个消息订阅器depend来专门手机这些订阅者,然后在监听器和订阅者之间进行统一管理。
- 接着还需要一个指令解析器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子组件模板如下:
在父组件内调用该组件时添加一些class:
渲染出来的HTML为:
class的绑定也是同样的:
当isActive为真是,被渲染的组件是:
如果你的组件有多个根元素,需要指定那个根元素来接收这个class,可以通过组件的$attrs属性来实现指定:
被渲染为:
以上这些模式叫做透传attribute。
在同一个标记上使用v-if和v-for,v-if会优先执行
在vue3中同一个标记上使用v-if和v-for,v-if会优先执行,它的优先级比v-for高。
如果想同时写的话可以将v-for写在templace上。将要操作的DOM用templace包裹起来。
注意同时使用v-if和v-for是不推荐的,因为二者的优先级。如果不注意的话v-if的条件将无法访问到v-for作用域内定义的变量名。
setup
在vue3中,使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下散步来建立反应性数据:
- 从vue引入reactive
- 使用reactive()方法来声明我们的数据为响应性数据
- 使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据。
vue2与vue3的生命周期
- setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
- onBeforeMount() : 组件挂载到节点上之前执行的函数。
- onMounted() : 组件挂载完成后执行的函数。
- onBeforeUpdate(): 组件更新之前执行的函数。
- onUpdated(): 组件更新完成之后执行的函数。
- onBeforeUnmount(): 组件卸载之前执行的函数。
- onUnmounted(): 组件卸载完成后执行的函数
若组件被keep-alive包含,则多出下面两个钩子函数。 - onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行 。
- onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。