Vue2及vue3原理

一、vue2

1.keep-alive是什么?它的原理是什么?

   keep-alive是Vue中内置的一个抽象组件,用来缓存动态组件,避免重复渲染组件。

生命周期:

   keep-alive提供了两个生命钩子,分别是activateddeactivated

  •    初次进入组件时:beforeCreate -> created -> beforeMount -> mounted -> activated
  •    再次进入:会触发activated,事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中

原理:   

  在内部维护了一个keys数组和一个cache缓存对象。keys数组会记录缓存组件的key值,若没有指定key值就会自动生成一个唯一的key值。cache对象会以key值为键,vnode为值,然后缓存组件对应的虚拟 DOM。在keep-alive 渲染阶段会拿key值到cache对象中去找是否有值,如果有就从缓存中取 vnode 的组件实例,如果没有则进行缓存。当缓存数量超过max设置数值时keep-alive会删掉key数组中的第一个元素,并重新调整该组件key的顺序。

缓存机制:

根据key在this.cache中查找,如果存在则说明之前已经缓存过了,直接将缓存的vnode的componentInstance(组件实例)覆盖到目前的vnode上面。否则将vnode存储在cache中。最后返回vnode(有缓存时该vnode的componentInstance已经被替换成缓存中的了)。缓存的处理:

/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */
if (cache[key]) {
    vnode.componentInstance = cache[key].componentInstance
    /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */
    remove(keys, key)
    keys.push(key)
} 
/* 如果没有命中缓存,则将其设置进缓存 */
else {
    cache[key] = vnode
    keys.push(key)
    /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
    if (this.max && keys.length > parseInt(this.max)) {
        pruneCacheEntry(cache, keys[0], keys, this._vnode)
    }
}
/* 最后设置keepAlive标记位 */
vnode.data.keepAlive = true

命中缓存时会直接从缓存中拿 vnode 的组件实例,此时重新调整该组件key的顺序,将其从原来的地方删掉并重新放在this.keys中最后一个。

如果没有命中缓存,即该组件还没被缓存过,则以该组件的key为键,组件vnode为值,将其存入this.cache中,并且把key存入this.keys中。此时再判断this.keys中缓存组件的数量是否超过了设置的最大缓存数量值this.max,如果超过了,则把第一个缓存组件删掉。

为什么要删除第一个缓存组件并且为什么命中缓存了还要调整组件key的顺序?这其实应用了一个缓存淘汰策略LRU:
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

this.keys的逻辑:

  1. 将新数据从尾部插入到this.keys中
  2. 每当缓存命中(即缓存数据被访问),则将数据移到this.keys的尾部
  3. 当this.keys满的时候,将头部的数据丢弃
2.nextTick的原理是什么?

在下次DOM更新循环结束之后执行的延迟回调。

工作原理:基于js的事件循环机制  和  vue的异步更新策略

因为数据发生变化时,视图不会立即更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。所以修改完数据,立即在方法中获取DOM,获取的仍然是未修改的DOM。此时,使用nextTick来确保在DOM更新后,执行某些操作。

好处:可以将多次数据更新合并成一次,减少操作DOM的次数。提高性能

场景:需要在数据更新后,基于最新生成的dom进行操作,就将这个操作放在nextTick的回调中。

1. 在钩子函数created()里面想要获取操作Dom,把操作DOM的方法放在$nextTick中

2. 点击按钮显示原本以 v-show = false 隐藏起来的输入框,并获取焦点。

3.

二、vue3

1.虚拟dom是什么?好处是什么?

虚拟DOM,是把页面中的真实DOM的结构和状态,抽象成一个javascript对象来表示。

原理:(内部使用 diff 算法,找到状态的差异,只更新变化的部分)

  1. 虚拟DOM就是将当前页面的 DOM 树映射为一个 JavaScript 对象形式的虚拟 DOM。
  2. 然后当应用程序状态发生改变时,根据新状态生成一个新的虚拟 DOM。
  3. 比较新旧两个虚拟 DOM 的差异,得到需要进行修改的 DOM 元素。
  4. 根据差异列表,对有修改的 DOM 元素进行实际的 DOM 操作,使浏览器重新渲染。

好处:

1. 最小化DOM操作:虚拟DOM可以通过差异对比算法找出需要更新的部分,只对这些部分进行操作,而不是整个DOM树。相比直接操作真实DOM,这样可以大幅度减少DOM操作的次数,提高性能。

2. 批量更新:虚拟DOM可以将多次DOM操作合并为一次,通过批量更新的方式减少浏览器的重绘和回流次数,提高渲染性能。

3. 跨平台兼容性:虚拟DOM是基于JavaScript对象树,因此可以在不同平台上使用相同的代码逻辑。这意味着可以在服务器端生成虚拟DOM,然后将其发送给客户端,减少了网络传输的数据量,提高了页面加载速度。

4. 开发效率提升:虚拟DOM可以将视图和状态分离,通过声明式的方式描述用户界面,提供了更高级别的抽象。这样可以使得开发者更专注于业务逻辑,减少了手动操作DOM的复杂性,提高开发效率。

缺点:首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比直接使用真实 dom 渲染慢 ;

2.vue2和vue3的响应式原理区别? 

vue2:采用 数据劫持 结合 发布者/订阅者模式实现的。通过 Object.defineProperty 方法,来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

主要分为以下几 个步骤:

  1. 需要 observe 的数据对象进行递归遍历,包括子属性对象的属性, 都加上 setter 和 getter 这样的话,给这个对象的某个值赋值,就会 触发 setter,那么就能监听到了数据变化,如果发生变化,就通知订阅者。
  2. compile 解析模板指令,将模板中的变量替换成数据,然后初始化 渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数 据的订阅者,一旦数据有变动,收到通知,更新视图
  3. Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做 的事情是: 1在自身实例化时往属性订阅器(dep)里面添加自己 2 自身必须有一个 update()方法 3待属性变动 dep.notice()通知时, 能调用自身的 update()方法,并触发 Compile 中绑定的回调,则功 成身退。
  4. MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。

缺点:

无法监听新增属性、删除属性,需要使用Vue.set,Vue.delete

无法监听数组的变化,需要手动特殊处理

vue3:基于 Proxy 和 Reflect 的 ES6 特性,使用ES6的Proxy代替了Vue 2中的Object.defineProperty,Proxy可以监听对象的任何属性变化,包括新增和删除属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值