聊一聊,vue3 的心智负担真的比 react 低吗?

20,001 阅读3分钟

前言

在很多地方都能看到 react hooks 的心智负担很重的说法,大部分是认同的。但是我认为 vue3 的心智负担也是不轻。这两者谁更重,我们可以一起来聊一聊,说出各自的看法。

react 的心智负担

react hook 常年被诟病的毛病想必大家都知道。不能在条件语句中使用,useMemouseCallback 需要显式指定依赖,解决子组件重新渲染可能还需要配合 React.memo 使用等等。虽然有对应的 eslint-plugin 可以帮助填充依赖,但是依赖项一旦很多,代码的可能读会非常差。现在普遍的观点是计算量大的再用 useMemo, 而 useCallback 能不用就不用。因为这点优化对性能的影响是微乎其微的,99% 的情况下都不会出现问题,等到出现问题的时候再进行优化也不迟。 react-forgot 项目(不需要显式指定依赖)的主负责人黄玄最近从 facebook 离职了,不知道有生之年还能不能等到它的发布了。

vue3 的心智负担

定义状态

refreactive 两种方法,且 refscript 标签中使用时还需要加一个 .value。虽然有了 $ref 语法糖,但最新已经废弃了。把 ref 定义的状态放在 reactive 里也要注意,否则会丢失同步。一些情况下还要区分代理对象和原始对象的不同。还有使用 console.log 打印的时候,在控制台查看很不直观。因为使用的是 Proxy 进行响应式,添加了诸如 isProxyunrefisRef 等 api。解构 props 也会出现响应丢失的问题,还要使用 toRefs 来解决。比如想把 props 的某个属性传递给一个组合式函数时,还需要用 toRef 来保持同步。还衍生出 shadllowRefshadllowReactivetriggerRef 等等诸多 api。

插槽

每个从 react 转到 vue 的人估计都会抱怨这东西的难用。因为在 react 中万物皆 props,想传什么就传什么。在 vue 中还要 具名插槽作用域插槽 等概念。

props 和 emits 的定义

属性事件 还需要分成 definePropsdefineEmits 两个 api。反观 react,还是万物皆 props 的说法。props 的默认值定义值也很麻烦,需要用到 withDefaults

侦听 watch

watch 监听对象里的某个属性时,第一个参数还需要是一个函数。还分为好多种,watchwatchPostEffectwatchSyncEffectwatchEffectwatch 的第三个参数又有很多属性。

渲染函数

vue3 提供了一个 h 函数,但还是很难用,这就是为什么很多组件库都选择了 tsx 的原因。

typescript 支持

存在语法限制。给 defineProps 定义的 ts 类型,不能从其它文件导入,只能写在这个文件里。想分开写到别的文件,只能不使用 ts 来定义类型,要使用 defineProps 的第一个参数来指定类型,这样才能从别的文件导入了。这就是为什么大多数组件库没有使用 ts 来定义类型的原因,这样定义的类型要用 ExtractPropTypes 来提取 ts 类型。

breaking change

vue2 升级到 vue3 是不兼容的,旧项目升级是很麻烦的。但 vue2 又不是不能用,不升级就行了。等新项目再使用 vue3。反观 react,几乎是没什么影响的,但另一方面这也带来沉重的历史包袱。

结尾

vue3 的优点很多,但是固然也存在一些心智负担,api 之多你也可以认为这是 feature,想要记住这么多 api 并熟练使用是不容易的。人家 api 这么多都给出来了,怎么记住怎么实现功能是你们的事。仅代表个人观点,我觉得 vue3 的心智负担更重一些。你们认为 vue3react 哪个对你来说心智负担更重呢,可以表达表达你们的看法。非引战,请理性讨论