VUE3的设计目标是什么,做了哪些优化

概要

vue无疑是当下构建单页应用程序最方便快捷的前端框架,因此得以在前端生态社区流行,得到越来越多相关从业人员或者兴趣爱好者的追捧。在vue2.0时代,得益于组件化和数据驱动的思想,简单小巧的核心,渐进式技术栈,足以应付大多数的应用场景。但vue2.0的设计仍然存在很多不足,使得推出vue3.0势在必行,vue3.0使得应用更小更快更易维护,是未来前端生态发展的趋势。

vue3推出的背景

在vue2时代,我们在开发过程中面临一下问题:

  • 随着业务功能的急速增长,复杂组件的代码变得越来越难以维护
  • 缺少一种纯净的提取机制(使得多个组件之间逻辑的复用变得清晰易于维护)
  • 类型推断不够友好,代码写的不够畅快
  • bundle的时间相对较长(因为使用webpack,所以打包机制决定了打包效率)

vue3的设计目标

打包体积更小
移除了一些不常用的API,引入tree-shaking机制,可以将无用模块剪切,只打包需要的模块,使得打包的体积整体变小。

速度更快
主要在以下方面做了优化

  • diff算法优化
  • 静态提升
  • 事件监听缓存
  • SSR优化

更灵活的代码组织能力
vue3在兼顾vue2的 options API的基础上,增加了composition API,大大增加了代码的逻辑组织和代码复用能力,并且vue3使用typescript开发,可以获得更好的类型提示体验

优化方案

vue3从很多层面都做了优化,总体可以从三个方面展开:

  • 源码
  • 性能
  • 语法API

源码

vue3整个源码是通过 monorepo的方式维护的,根据功能将不同的模块拆分到packages目录下面不同的子目录中。
这样使得模块拆分更细化,职责划分更明确,模块之间的依赖关系也更加明确,开发人员也更容易阅读、理解和更改所有模块源码,提高代码的可维护性

vue3基于typeScript编写,提供了更好的类型检查,可以支持复杂的类型推导

性能

vue3从以下方面对性能做了优化:

  • 体积优化
  • 编译优化
  • 数据劫持优化

下面从数据劫持方面看看做了什么优化:

在vue2中,数据劫持是通过Object.defineProperty,这个 API 有一些缺陷,并不能检测对象属性的添加和删除

Object.defineProperty(data, 'msg',{
  get(){
    // track
  },
  set(){
    // trigger
  }
})

尽管Vue为了解决这个问题提供了 set和delete实例方法,但从开发使用上来说,还是增加了开发的一些负担

同时在面对嵌套层级比较深的情况下,存在性能问题

export default {
  data: {
    a: {
      b: {
          c: {
            d: []
          }
      }
    }
  }
}

相比之下,vue3是通过proxy监听整个对象,那么对于删除或者赋值都可以监听到,
但是Proxy 并不能监听到内部深层次的对象变化,Vue3 的处理方式是在getter中去递归响应式,这样的好处是真正访问到的内部对象才会变成响应式,而不是无脑递归,减少性能的开销。

语法 API

这里说的就是composition API,其优势主要体现在两方面:

  • 优化逻辑组织
  • 优化逻辑复用

之前在2.x 系列我们的写法可以成为Option API简单理解根据配置项去按照规则将对应代码放到
对应的配置项中,对应的产生了三个问题

  • 随着组件变得更大的可读性变得越来越困难尤其大型组件
  • 不利于代码重用,即使有Mixins方案整体也有一些问题
  • Vue 2提供了有限的TypeScript支持

options api动画演示

组件之间重用
2.x 也提供了三种重用解决方案Mixins,Mixin工厂,作用域插槽

Composition API 就可以让同一个功能的代码放到一起,查看修改的时候不用一个文件到处跳
Composition API 是根据逻辑相关性组织代码的,提高可读性和可维护性
基于函数组合的 API 更好的重用逻辑代码(在vue2 Options API中通过Mixins重用逻辑代码,容易发生命名冲突且关系不清)

composition api动画演示

Composition Api 解决大型组件维护问题

  • 如果将功能代码保持在一起这样代码可读性、可维护性,3.x 提供了新的api setup,这是一个可选的
    也就是说'3.x' 是同时支持Composition API 和Option API 两种编写习惯的
  • 如果将代码都构建在setup中,是否会出现一个庞大的setup 冗杂这各种逻辑在里面,这个问题不用担心
    如下图给出的方案'会将功能分组为可通过设置方法调用的组合功能

逻辑组织
相同功能的代码编写在一块,而不像options API那样,各个功能的代码混成一块

逻辑复用
在vue2中,我们是通过mixin实现功能混合,如果多个mixin混合,会存在两个非常明显的问题:命名冲突和数据来源不清晰
而通过composition这种形式,可以将一些复用的代码抽离出来作为一个函数,只要在使用的地方直接调用即可

下面是获取鼠标位置的例子:

import { toRefs, reactive, onUnmounted, onMounted } from 'vue';
function useMouse(){
    const state = reactive({x:0,y:0});
    const update = e=>{
        state.x = e.pageX;
        state.y = e.pageY;
    }
    onMounted(()=>{
        window.addEventListener('mousemove',update);
    })
    onUnmounted(()=>{
        window.removeEventListener('mousemove',update);
    })

    return toRefs(state);
}

在组件中使用该功能:

import useMousePosition from './mouse'
export default {
    setup() {
        const { x, y } = useMousePosition()
        return { x, y }
    }
}

可以看到,整个数据来源清晰了,即使去编写更多的hook函数,也不会出现命名冲突的问题

参考文献

posted @ 2021-09-07 20:46  Elwin0204  阅读(417)  评论(0编辑  收藏  举报