Vue3特性以及相较于Vue2的优化点

631 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

Vue3特性

  • RFC机制可以让所有人参与Vue新语法的讨论
  • Vite让开发调试变得更加丝滑
  • Vue3性能更好(渲染/打包),体积更小,内存占用减少
  • 组合式API可以更好的组织代码(避免Vue2上蹿下跳式开发),响应式基于Proxy,且可以独立使用。
  • Vue3新增 Fragment、Teleport和Suspense组件
  • Vue3重写了虚拟DOM的实现,让diff更快。重写了Tree-shaking,减少打包体积。
  • 对于Vue3,由于模块分离,便于二次开发,可以通过自定义渲染器来开发各种跨端应用
  • Vue3拥抱TypeScript,更好的可维护性

Vue2的缺陷和Vue3的改进

引入TypeScript类型支持

Vue2基于Flow.js来做类型校验,而现在整个社区都在采用TS来构建基础库。因此Vue3不再使用FaceBook的flow.js,用TS重构了,引入类型系统可以方便代码提示,同时可以让代码更健壮。

响应式系统的进一步完善

Vue2采用defineProperty的形式

defineProperty :

const obj = {};
// 监听obj上的text属性
Object.defineProperty(obj, 'text', {
  get: function() {
    console.log('get val');
  },
  set: function(newVal) {
    console.log('set val:' + newVal);
    document.getElementById('input').value = newVal;
    document.getElementById('span').innerHTML = newVal;
  }
});

const input = document.getElementById('input');
input.addEventListener('keyup', function(e){
  obj.text = e.target.value;
})
  • defineProperty是对属性进行拦截,因此Vue2所有的数据需要在data中声明
  • 但是如果data中的数据为引用类型时,对数据的操作不会改变地址,比如数组虽然可以通过Vue重写过的push来实现视图更新,但是对于数组的长度修改还是无法实现,因此需要$set等API。以及对对象属性删除时也监听不到,需要额外去补充。

而Vue3用的是Proxy+Reflect:可以深度监听,但是不支持IE11以下浏览器

const input = document.getElementById('input');
const p = document.getElementById('p');
const obj = {};

const newObj = new Proxy(obj, {
  get: function(target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function(target, key, value, receiver) {
    console.log(target, key, value, receiver);
    if (key === 'text') {
      input.value = value;
      p.innerHTML = value;
    }
    return Reflect.set(target, key, value, receiver);
  },
});

input.addEventListener('keyup', function(e) {
  newObj.text = e.target.value;
});
  • 真正的代理,拦截数据,但是对于数据格式不关心,统一都拦截(属性删除也可以),还可以监听Set, Map等,这是Vue2无法做到的。
  • 但是无法兼容IE11以下的浏览器。

上窜下跳Option式写法变为逻辑分离的Composition

Options API有很严重的问题

  • 所有数据都挂载在当前实例的this上,这样的写法不利于TypeScript的类型推导,而且不好做Tree-shaking(消除无用模块代码)清理代码。
  • 代码行数多了以后需要反复上下横跳,开发起来体验比较痛苦。
  • 代码不利于复用,Vue2的组件比较难抽离通用逻辑,用mixin的话还会有命名冲突问题。

Composition API的好处:

  • 所有API都是通过import引入的,用到的功能才import进来,利于Tree-shaking,便于优化包的大小。
  • 代码易于复用,可以将一个功能所有的methods,data封装到一个独立函数中,复用变的容易。
  • Composition API新增的return等语句,使用

Options和Composition的对比图

Image.png

可以看到Options API当你处理一段功能逻辑时得上下横跳,尤其是代码段多起来以后非常烦。而Vue3的Composition API则在功能上是分离的,逻辑更清晰,代码也会更清爽。

对比一下Vue2使用的Options API 和Vue3推荐的 Composition API

Image.png

Image.png

可以看到Composition API显的有一些繁琐,不如Options API那样分方法、数据之类的清晰,但是可以发现,业务逻辑被分离了,可以一行注释将一部分业务逻辑包裹起来,这样更便于后期维护和迭代。

新的内置组件

Fragment: Vue3不需要像Vue2一样template下必须有唯一根节点。

Teleport: 允许组件渲染在别的元素内,主要在开发弹窗组件的时候特别有用。

Suspense: 异步组件(猜测和React的相似),更便于开发有异步请求的组件

Vite 新一代工程化工具

复杂项目如果通过webpack预打包放内存中调试的话需要花费很多时间,而vite就是为了解决这样的时间消耗。

Vite是基于现代浏览器默认支持ES6中import语法来实现的。具体是在调试环境下,不需要全部预打包,仅将首页依赖的文件依次通过网络请求去获取,让整个开发体验变得很好,对于复杂项目可以做到秒级调试和热更新

webpack和vite对比

webpack需要将所有路由的依赖打包完毕后才可以调试

Image.png

vite一开始仅需要加载首页的依赖模块,然后根据跳转路由时按需加载

Image.png