3-5模块作业(Vue.js 3.0)

121 阅读3分钟

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

  • 响应式系统升级:Vue2.0是在数据初始化之后,遍历对象的属性通过Object.defineProperty监听属性的变化。vue3.0采用Proxy代理对象拦截对象的访问,可以监听动态新增的属性、删除的属性、数组的索引和length属性。
  • 编译优化:Vue2.0中渲染的最小单位是组件,会标记静态根节点,优化diff的过程,但静态节点还要通过diffVue2.0中会标记所有的静态节点,diff的过程只需要对比动态节点内容。
    • Fragments(片段):组件内支持多个同级的根标签
    • 静态提升:标签中仅仅是纯文本的节点,会提升到render函数外,再次render无须再次创建
    • Patch flag: 标记不同类型的节点(如动态文本节点、有动态属性的节点),优化diff的过程
    • 缓存事件处理函数、组件按需动态导入
  • 源码体积优化
    • Vue3.0中移除了一些不常用API,如:inline-templatefilter
    • Tree-shaking(依赖ESmodule的模块化规范)

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

  • Vue2.0中的Options API包含描述组件选项(datamethods等)的对象,在描述复杂组件时,同一功能的逻辑被拆分到不同的选项中,随着版本的迭代难以维护
  • Vue3.0中的Compositon API新增一组基于函数的API,可以更加灵活的组织同一个功能的代码片段
  • Vue3.0中的setup(props, context){}在实例被初始化之前执行,故在setup中的this上没有任何东西

3、Proxy 相对于 Object.defineProperty 有哪些优点?

  • Proxy直接监听对象而非属性,有多达13种拦截方法,如 applyownKeyshas 等等,这是Object.defineProperty不具备的
  • 多层属性嵌套,在访问属性过程中处理下一级属性
  • 默认监听动态添加的属性
  • 默认监听属性的删除操作
  • 默认监听数组索引和length属性  

4、Vue 3.0 在编译方面有哪些优化?

  • Vue2.0中渲染的最小单位是组件,会标记静态根节点,优化diff的过程,但静态节点还要通过diffVue2.0中会标记所有的静态节点,diff的过程只需要对比动态节点内容。
  • Fragments(片段):组件内支持多个同级的根标签
  • 静态提升:标签中仅仅是纯文本的节点,会提升到render函数外,再次render无须再次创建
  • Patch flag: 标记不同类型的节点(如动态文本节点、有动态属性的节点),优化diff的过程
  • 缓存事件处理函数、组件按需动态导入

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

  • Vue3.0使用Proxy对象重写响应式系统
  • Proxy代理拦截:
    • reactive函数执行,会将传入的target对象通过Proxy包装,拦截它的getset等,并将代理的target缓存到targetMaptargetMap.set(target, new Map())。 代理的get的时候会调用一个track函数,而set会调用一个triger函数。分别对应依赖收集和触发更新。
export function reactive (target) {
  if (!isObject(target)) return target

  const handler = {
    get (target, key, receiver) {
      // 收集依赖
      track(target, key)
      const result = Reflect.get(target, key, receiver)
      return convert(result)
    },
    set (target, key, value, receiver) {
      const oldValue = Reflect.get(target, key, receiver)
      let result = true
      if (oldValue !== value) {
        result = Reflect.set(target, key, value, receiver)
        // 触发更新
        trigger(target, key)
      }
      return result
    },
    deleteProperty (target, key) {
      const hadKey = hasOwn(target, key)
      const result = Reflect.deleteProperty(target, key)
      if (hadKey && result) {
        // 触发更新
        trigger(target, key)
      }
      return result
    }
  }

  return new Proxy(target, handler)
  • 依赖收集和触发更新:
    • 组件在render阶段,视图会读取数据对象上的值进行渲染,此时便触发了Proxyget,由此触发对应的track函数,记录下了对应的ReactiveEffect,也就是依赖收集。
    • ReactiveEffect其实就可以看作是组件的更新(mount是特殊的update),数据的变更触发triggertrigger遍历调用track收集的对应的数据的ReactiveEffect,也就是对应有关联的组件的更新。trigger触发的组件的更新,在render阶段又触发了新一轮的track依赖收集,更新依赖