4、vue3所采用的composition Api与vue2的Options Api有何不同?
1、vuediff算法的理解
定义:diff算法是一种通过同层树节点进行比较的高效算法
两个特点:
比较只会在同层级进行,不会跨层级比较
在diff比较的过程中,循环从两边向中间比较
应用场景很多,在vue中,作用于虚拟dom渲染成真实dom的新旧VNode节点比较
原理:diff算法遵循同层比较,深度优先
当数据发生改变时,set方法会调用Dep.notify通知所有订阅者watcher,订阅者就会调用patch给真实dom打补丁,更新对应的视图
patch前两个参数为oldValue和Vnode,分别代表旧节点和新节点,主要做了四个判断:
- 没有新节点,直接触发旧节点的destory钩子
- 没有旧节点,说明页面是刚开始初始化时候,此时,不需要比较,直接新建,只调用createRlm
- 旧节点和新节点自身一样,通过sameVnode判断节点是否一样,一样时,调用patchVnode去处理这两个节点
- 旧节点和新节点自身不一样,两个节点不一样时,直接创建新节点,删除旧节点
patchVnode主要做了几个判断:
- 新节点是否是文本节点,如果是,直接更新dom的文本内容为新节点的文本内容
- 新旧节点都有子节点的情况下,则处理比较更新子节点(diff算法核心)
- 只有新节点有子节点,旧节点没有,那么不用比较,所有节点都是全新的,直接新建dom,添加进父节点中就行
- 只有旧节点有子节点,说明更新后的页面,旧节点全部不见了,所以,把所有的旧节点删除,也就是直接把dom删除
2、为什么使用虚拟dom
虚拟dom实际上是对真实dom的抽象,以javascript对象作为基础的树,用对象的属性来描述节点,最终通过一系列操作使得这棵树映射到真实环境上
在js对象中,虚拟dom是一个object对象,至少包含标签名(tag)、属性(attrs)和子元素对象(children)三个属性,不同框架对这三个属性命名可能会有差别
为什么使用虚拟dom?
DOM是很慢的,其元素非常庞大,页面的性能问题,大部分都是有dom引起的
在原生dom操作,浏览器会从构建dom树开始从头到尾执行一遍流程
当你在一次操作时,需要更新10个
DOM
节点,浏览器没这么智能,收到第一个更新DOM
请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程而通过
VNode
,同样更新10个DOM
节点,虚拟DOM
不会立即操作DOM
,而是将这10次更新的diff
内容保存到本地的一个js
对象中,最终将这个js
对象一次性attach
到DOM
树上,避免大量的无谓计算很多人认为虚拟 DOM 最大的优势是 diff 算法,减少 JavaScript 操作真实 DOM 的带来的性能消耗。虽然这一个虚拟 DOM 带来的一个优势,但并不是全部。虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是近期很火热的小程序,也可以是各种GUI
3、Vue3.0的设计目标是什么? 做了哪些优化
vue3之前的问题:
- 随着功能的增长,复杂组件的代码变得越来越难以维护
- 缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制
- 类型推断不够友好
bundle
的时间太久了vue3设计目标:更小,更快,ts支持,api设计一致性,提高自身可维护性,开放更多底层功能
更小:移除一些不常用的api,引入tree-shaking,把无用的模块剪辑掉,减少打包之后的体积
更快:
- diff算法优化
- 静态提升
- 事件监听缓存
- ssr优化
更优化:v3的组合是api兼容v2的选项式api,提高代码的逻辑组织和代码复用能力
优化方案:
源码
vue3的项目管理通过monorepo方式管理的,方便开发者阅读和更改,提代码的可维护性
vue3基于ts编写的,提供了很好的类型检查,支持复杂的类型推导
性能
体积优化
编译优化
数据劫持优化
语法Api
优化逻辑组织
优化逻辑复用
在
vue2
中,我们是通过mixin
实现功能混合,如果多个mixin
混合,会存在两个非常明显的问题:命名冲突和数据来源不清晰而通过
composition
这种形式,可以将一些复用的代码抽离出来作为一个函数,只要的使用的地方直接进行调用即可
4、Vue3.0 所采用的 Composition Api 与Vue2.x 使用的 Options Api 有什么不同?
一、Options API?
options API就是大家常说的选项API,也就是以.vue为后缀名的文件,通过定义的methods,computed,watch,data等属性和方法,共同处理页面的逻辑二、Composition API?
在vue3 的composition API中,组件根据逻辑功能来组织的,一个功能所定义所有的API会放在一起(更加的高内聚低耦合),也就是即使我们的项目很大,功能很多的时候,我们都能快速的定位到这个功能所用到的所有的API三、对比区别?
Options API 是将组件的选项分散在不同的属性中,如 data、methods、computed、watch 等,而 Composition API 则是将组件的逻辑按照功能进行组合,使得代码更加清晰、易于维护。Options API 中的 data、computed、watch 等属性都是在组件实例化时被初始化的,而 Composition API 中的响应式数据需要使用 ref 或 reactive 进行声明和初始化。
Options API 中的 methods 中的函数可以直接在模板中调用,而 Composition API 中的函数需要通过返回值暴露给模板使用。
Composition API 中的 setup 函数是在组件实例化之前执行的,可以用来进行一些初始化操作,而 Options API 中的 created、mounted 等生命周期函数是在组件实例化之后执行的。
小结:
Composition API 更加灵活
,可以更好地组织组件逻辑,使得代码更加清晰、易于维护。
5.说一下Vue数据响应式的原理?
Vue2 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty0来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。主要分为以下几个步骤:
1,需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
2.compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
3.Watcher订阅者是observer和Compile之间通信的桥梁,主要做的事情是: @在自身实例化时往属性订阅器3 dep)里面添加自己 @自身必须有一个update0方法 的待属性变动dep.notice0通知时,能调用自身的update0方法,并触发Compile中绑定的回调,则功成身退。
4.MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的mode数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 ->视图更新,视图交互变化(input) -> 数据model变更的双向绑定效果
vue3响应式原理
实现原理:
通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写,属性的增加,属性的删除等。通过Reffect(反射): 对源对象的属性进行操作
proxy
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)
const p = new proxy(target,handler)
target:
要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。handler:
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为Reffect
Reflect是一个组合的对象,它提供了阻止 JavaScript 操作的方法。Reflect不是一个函数对象,因此它是不可构造的。
在reffect身上,就有
defineProperty()
这个方法