Vue3相关

Composition Api 与 Vue 2.x使用的Options Api 有什么区别?

Options Api

包含一个描述组件选项(data、methods、props等)的对象 options;

API开发复杂组件,同一个功能逻辑的代码被拆分到不同选项 ;

使用mixin重用公用代码,也有问题:命名冲突,数据来源不清晰;

composition Api

vue3 新增的一组 api,它是基于函数的 api,可以更灵活的组织组件的逻辑。

解决options api在大型项目中,options api不好拆分和重用的问题。

Proxy 相对于 Object.defineProperty

proxy的性能本来比defineproperty好,proxy可以拦截属性的访问、赋值、删除等操作,不需要初始化的时候遍历所有属性,另外有多层属性嵌套的话,只有访问某个属性的时候,才会递归处理下一级的属性。

  • 可以* 监听数组变化
  • 可以劫持整个对象
  • 操作时不是对原对象操作,是 new Proxy 返回的一个新对象
  • 可以劫持的操作有 13 种

Vue3和Vue2对比,哪些方面更加出色?

2.x和3.x原理分析

  • Vue.js 2.x 中响应式系统的核心是 Object.defineProperty,劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter和setter,实现响应式
  • Vue.js 3.x 中使用 Proxy 对象重写响应式系统 可以监听动态新增的属性 可以监听删除的属性 可以监听数组的索引和length属性
  • 实现原理: 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
  • 通过Reflect(反射): 对源对象的属性进行操作。 MDN文档中描述的Proxy与Reflect:
new Proxy(data, {
    // 拦截读取属性值 
    get (target, prop) { 
        return Reflect.get(target, prop) 
    },
    // 拦截设置属性值或添加新属性 
    set (target, prop, value) {
        return Reflect.set(target, prop, value) 
    },
    // 拦截删除属性
    deleteProperty (target, prop) { 
        return Reflect.deleteProperty(target, prop) 
    }
}) 
proxy.name = 'tom' ![]

Vue 3.0 性能提升主要是通过哪几方面体现的

  1. 响应式系统提升 vue2在初始化的时候,对data中的每个属性使用definepropery调用getter和setter使之变为响应式对象。如果属性值为对象,还会递归调用defineproperty使之变为响应式对象。

    vue3使用proxy对象重写响应式。proxy的性能本来比defineproperty好,proxy可以拦截属性的访问、赋值、删除等操作,不需要初始化的时候遍历所有属性,另外有多层属性嵌套的话,只有访问某个属性的时候,才会递归处理下一级的属性。 优势:

    • 可以监听动态新增的属性;
    • 可以监听删除的属性 ;
    • 可以监听数组的索引和 length 属性;
  2. 编译优化 优化编译和重写虚拟dom,让首次渲染和更新dom性能有更大的提升 vue2 通过标记静态根节点,优化 diff 算法 vue3 标记和提升所有静态根节点,diff 的时候只比较动态节点内容

    Fragments, 模板里面不用创建唯一根节点,可以直接放同级标签和文本内容

    静态提升

    patch flag, 跳过静态节点,直接对比动态节点,缓存事件处理函数

  3. 源码体积的优化 vue3移除了一些不常用的api,例如:inline-template、filter等 使用tree-shaking

Vue3.0 编译做了哪些优化?

生成 Block tree

  • Vue.js 2.x 的数据更新并触发重新渲染的粒度是组件级的,单个组件内部 需要遍历该组件的整个 vnode 树。在2.0里,渲染效率的快慢与组件大小成正相关:组件越大,渲染效率越慢。并且,对于一些静态节点,又无数据更新,这些遍历都是性能浪费。
  • Vue.js 3.0 做到了通过编译阶段对静态模板的分析,编译生成了 Block tree。Block tree是一个将模版基于动态节点指令切割的嵌套区块,每个 区块内部的节点结构是固定的,每个区块只需要追踪自身包含的动态节点。所以,在3.0里,渲染效率不再与模板大小成正相关,而是与模板中动态节点的数量成正相关。

slot 编译优化

  • Vue.js 2.x中,如果有一个组件传入了slot,那么每次父组件更新的时候,会强制使子组件update,造成性能的浪费。
  • Vue.js 3.0 优化了slot的生成,使得非动态slot中属性的更新只会触发子组件的更新。动态slot指的是在slot上面使用v-if,v-for,动态slot名字等会导致slot产生运行时动态变化但是又无法被子组件track的操作。c. diff算法优化(此知识点进大厂可能会问到,由于篇幅较长,大家可以去官网看下)

Vue.js 3.0 响应式系统的实现原理?

  1. reactive 设置对象为响应式对象。接收一个参数,判断这参数是否是对象。不是对象则直接返回这个参数,不做响应式处理。创建拦截器handerler,设置get/set/deleteproperty。 get

    收集依赖(track); 如果当前 key 的值是对象,则为当前 key 的对 象创建拦截器 handler, 设置 get/set/deleteProperty;

    如果当前的 key 的值不是对象,则返回当前 key 的值。 set 设置的新值和老值不相等时,更新为新值,并触发更新(trigger)。 deleteProperty 当前对象有这个 key 的时候,删除这个 key 并触发更新(trigger)。

  2. effect 接收一个函数作为参数。作用是:访问响应式对象属性时去收集依赖

  3. track 接收两个参数:target 和 key

  • 如果没有 activeEffect,则说明没有创建 effect 依赖
  • 如果有 activeEffect,则去判断 WeakMap 集合中是否有 target 属性
  • WeakMap 集合中没有 target 属性,则 set(target, (depsMap = new Map()))
  • WeakMap 集合中有 target 属性,则判断 target 属性的 map 值的 depsMap 中是否有 key 属性
  • depsMap 中没有 key 属性,则 set(key, (dep = new Set())) -depsMap 中有 key 属性,则添加这个 activeEffect
  1. trigger 判断 WeakMap 中是否有 target 属性,WeakMap 中有 target 属性,则判断 target 属性的 map 值中是否有 key 属性,有的话循环触发收集的 effect()。
对你有帮助?请作者喝杯咖啡~
 支付宝 支付宝
 微信 微信
0%