升级 Vue3 大幅提升开发运行效率

本文介绍了 Vue3 的升级过程、原因和带来的新特性,如 Proxy 代理、Composition API、自定义 Hooks 和性能提升。通过实际案例,展示了 Vue3 如何提高开发效率,以及在项目中如何平滑升级。升级后,Vue3 的 SSR 性能提高了 2~3 倍,整体性能提升了 1.3~2 倍,降低了心智成本,增强了代码可维护性。
摘要由CSDN通过智能技术生成

作者:louiszhai,腾讯 IEG 前端开发工程师

Vue3 性能提升了 1.3~2 倍,SSR 性能提升了 2~3 倍,升级 Vue3 正是当下。

背景

原计划 2019 年发布的 Vue3,又经过一年的再次打磨,终于于去年 9 月正式发布。随后,不少 UI 组件库都积极参与适配,去年 12 月,Element-plus(Element-ui 官方升级版)也发布了 beta 版。

由于项目中用到了 Element-ui 组件,组件库未适配的情况下,不敢贸然升级 Vue3。Element-plus 发布后,又经过 1 个月的观察、测试和调研,发现 Element-plus 相对成熟(还有少量 bug,后续会讲),便开始尝试升级 Vue3。

如何升级 Vue3

有两种方案可以快速升级 Vue3:

  • 一种是使用微前端轮子,我基于 qiankun2,搭建了 Vue3 项目基座,为了保证平稳升级,子项目继续使用 Vue2,然后不断的把子项目的页面迁移到基座项目。

  • 另一种是,直接升级 Vue3,将项目中的 Vue2 依赖库升级到 Vue3 的最新版(当前最新版是v3.0.11),并且稍微改造 webpack 编译脚本,使之适配 Vue3。

之所以会有方案一,主要还是担心 Element-plus 不够稳定,如果有天坑,又无法绕过去,除了向饿了么团队提交 PR,微前端兜个底也是不错的应急措施。

就这样微前端方案又运行了 1 个月,部分页面已完成升级,运行良好,实践证明 Element-plus 比想象中稳定,这增加了我对于方案二的信心。考虑到还有少量业务复杂的页面,在微前端模式下,子项目的各种数据多经过一层 qiankun 的 proxy 代理,性能有损耗,影响了页面更新,于是一次性将剩余的页面全部迁移到 Vue3 项目中。

实践证明,除非比较复杂的项目,或者依赖组件库没升级等原因不适合升级外,常规情况下,升级 Vue3 都是一个不错的选择。

为什么要升级 Vue3

为什么要升级 Vue3,这是一个几乎不需要回答的问题。升级 Vue3 后,代码结构更加清晰内聚,响应式数据流更加可控,节省了很多心智成本,从而使得开发效率大幅提升。Vue3 还带来了很多新特性,框架层面运行性能更高(性能提升了 1.3 至 2 倍,SSR 性能提升了 2 至 3 倍),Composition API 使得代码拆分,函数封装更容易,复杂项目也随之更容易管理。

Vue2 中,相关的逻辑经常分散在 option 的 data、watch、computed、created、mounted 等钩子中,阅读一段代码,经常需要上下反复横跳,带来了部分阅读障碍。钩子又依赖 Vue 实例,代码封装基于天生携带钩子的 Mixin 去做,更加容易和相对方便。

但正因为如此,Mixin 的钩子容易不自觉的越界,插手到页面或组件的内部变量和方法管理过程中;甚至,多个不同的 Mixin,相互之间就很容易冲突,项目开发者,在引入 Mixin 和避免冲突之间需要保持微妙的平衡,不但增加心智负担,还带来了副产品:本身扑朔迷离的 this 变得更加不确定。因此,大型项目 Mixin 几乎都是一种反模式。

现在这些框架问题,都由 Vue3 的 Composition API 解决了。

Vue3 带来了哪些新特性

我们先看一些立马能感受到变化的特性。

Proxy 代理

这是一个一上手 Vue3 就能感知的变化。即使你在 Vue3 中编写 Vue2 风格的基于 option 的代码,Proxy 也是默默提供着数据响应式。

const observe = (data) => {
  Object.keys(data).forEach((key) => {
    const initValue = data[key];
    let value = initValue;
    if (typeof initValue === 'object') {
      observe(initValue);
      return;
    }
    Object.defineProperty(data, key, {
      enumerable: true,
      configurable: true,
      get() {
        console.log('visit key value =', key, value);
        return value;
      },
      set(val) {
        console.log(`[${key}]changed,old value=${value}, new value = ${val}`);
        if(value !== val) {
          value = val;
        }
      }
    });
  });
};
const data = {};
Array.from(new Array(100), () => "").forEach((item, i) => {
  data[i] = { value: i * 2 };
});
console.time();
observe(data);
console.timeEnd(); // default: 0.225ms
data.a = { b: 1 };
data.a.b = 2;

如上所示,Vue2 的数据响应式是通过 Object.defineProperty 实现,这是一个深度遍历的过程,无论 data 中包含多少层数据,都需要全部遍历一遍。深度遍历,给对象的每个自身属性添加 defineProperty,需要不小的性能开销,同时后面新增到 this 中的属性不提供响应式监听,因此我们需要使用诸如this.$set这种方式去添加新属性。

Proxy 就没有这个问题,如下所示。

const observe = (data) => {
 return new Proxy(data, {
  get(target, key, receiver) {
   console.log('visit', key);
   return Reflect.get(target, key, receiver);
  },
  set(target, key, value, receiver) {
   console.log(`[${key}]changed, value = ${value}`);
   Reflect.set(target, key, typeof value ===
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值