近日突然看到“为什么Vue在国际上越来越没影响力”这样一个问题
如果Vue 单纯看 star 数量的话,确实比 React 多啊
说实话,Vue 实际上策略是紧跟 React,我们组内部讨论的时候,一般把 Vue 看作是全工具链的 React 框架,无论是老版本还是新版本
Vue 和 React 的原理性差异几乎没有,这点和 ng 不同,因为在开发 ng 的时候,编程思维都需要彻底转变才能进行
所以,你对 Vue 和 React 的比较,可能完全没有意义,因为绝大多数有能力的开发者,Vue React 双修基本没有太多额外成本,但是如果加入 ng,那成本就指数上升了
在响应式方面,Vue 和 React 都是数据驱动,简而言之就是,渲染的发生总是因为我修改了某个数据,细节差异你直接看 mobx 文档就能知道(数据变化应该自发地传递),也就是 Vue 加入 defineProperty 或者 proxy 的原因,实际上是对 React 在词法逻辑表达能力的优化,增强 React 的架构能力
这部分差异体现在使用上,也就是你在变量绑定时,是传 value onChange 两个参数,还是 v-model 一个参数,是定义 getter setter 绑定两个 state,还是 computed 传入 getter setter 绑定,在功能上是没有一点点差异的,也就可读性和命名负担以及纯度(质量控制)上有些许差异
这点和 ng 区别特别大,ng 渲染发生(或者脏检发生),不是因为你修改了某个数据,而是因为有异步发生,这个根本性不同,会导致编程思维根本性变化,比如,事件不需要你去做 batchUpdate,响应式也不需要考虑,反正视图总会响应,但是检查次数需要你去做限制,否则检查次数太过频繁,同时hmr将变得非常拉跨,补偿是逻辑组织能力非常强,意味着测试比调试容易
常用的分布式计算模型就两个,CSP 和 Actor,React 占了 CSP(用过 reducer 没?),ng 占了 Actor(别再问为啥 ng 没有状态管理了),所以没有多余的坑位给 Vue
虽然,React 选择社区最优第三方,其实是能够比 Vue 开发体验更好:
styled-components 比 Vue <style scoped/> + css module 效率更高
react-router 比 vue-router 灵活性更强(路由作为组件更方便挂载上下文,同时不会引入更多概念)
原生集成 csp useReducer 比引入 vuex 效率更高(一般来说我还是不喜欢外挂 csp)
但是,如果从统一语言的角度,React 是失败的,因为更多的社区选择意味着更多的可能应用形态,语言更加不统一,团队协作更加困难
这里也可以顺带解释 Vue 和 React 难易
同时,虽然更细划分的 csp 灵活性更强,但是总是需要传入的依赖数组也需要进行专门的学习和练习,就算现在,很多第三方 hooks 都没有强制传入 useCallback 吧?
所以,这就给 Vue 带来了机会,可以这么说,如果没有 Vue,React 生态也会自发出现一个类似 Vue 的 React “框架”,而且肯定比 Vue 拉跨
不过,Vue 的上一次跟进 Vue2 是成功的,原因是 React 16.8 以前的版本,实在是太屎了(不想回忆,此处省略 1000 字)
但是新版本 Vue3 的跟进还有待商榷,原因有以下几点:
- template 表达能力不够
这个问题其实一直存在,甚至很多没用过 ng 的朋友,还会争论 template 和 jsx 谁更强,实际上你用过 ng html+ 就知道,html 里写 js 和 js 里面写 html 表达能力是一样的,之所以有这个争论,原因就是 vue template 限制太大
比如 renderProps,实际上是可以写在 template 里的,比如 ng 模板引用变量:
//
<some-compo [someTemplate]="templateRef"></some-compo> <!-- 动态 template 想写在哪里都可以,不同组件甚至不同module --> <ng-template #templateRef> <div>this is render</div> </ng-template>
而 Vue 这部分能力还需要用 jsx,这就很坑人,也会导致很多社区生态直接全部采用 jsx 开发,相当于把开发者往 React 社区推,因为如果全局使用 jsx,Vue 相对于 React 的优势将荡然无存
还有 Vue 的 template 中无法随心所欲写 js/ts ,不过这个也说不清是优势还是劣势
不过好在现在终于有 ts 支持了
2. 调度拆分不够细
如果同步修改两个 ref/reactive ,watch 这两个 ref/reactive,只能获得一次变更
const a = ref(0) const b = ref(0) setTimeout(()=>{ a.value = 1 b.value = 1 },0) watch(()=>[a,b], console.log) // 只变化一次
这个问题其实挺严重的,因为如果你在中间修改了某个非响应式数据:
a.value = 1 someValue = true b.value = 1
这个 someValue 的变化,你无法在 watch 中捕获
再更进一步,这个 a,b 两个响应式变量的拆分,变的没有意义了,或许默认只有一个响应式变量更好一些?还能解决 ref/reactive 心智负担问题?毕竟拆分根本没有作用,他们并不是两个独立的响应式数据源
不过 Vue 还在演化阶段,不像 React 18 基本定型
3. Vue 没有 batchUpdate
这个其实更加让人疑惑,因为 batchUpdate 这个问题,出现在 Vue 比 出现在 React 更加让人恐慌
比如就拿上面的例子:
setTimeout(()=>{ a.value = 1 b.value = 1 },0) // watch 调用一次 setTimeout(()=>{ a.value = 1 },0) setTimeout(()=>{ b.value = 1 },0) // watch 调用两次
同一个事件循环,拆开成两个任务,就变化,一个任务,就不变,可能会造成双倍困惑,因为很多时候,开发时考虑事件循环就够了,没必要深入讨论到任务先后顺序上去,因为任务调度很多时候是不确定的,而事件循环是确定的,同时更抽象一层
4. 保留生命周期,兼容老版本
Vue 是框架,与 React 定位不同,这也是 Vue 的市场立足之本,开发过程是不会轻易更换或升级框架的,React 作为一个库,提供不同的 api,我只要不用历史 api,就能和老版本划清界限(比如,现在的 react 文档,只看 hooks 和部分 jsx ,你会觉得这是个简单到爆炸的库,反而你一看老版本的 屎化 react,你会被卷成卷心菜,比如最近好多人都在讨论 memo() , 也不知道在讨论写什么,还在纠结性能优化,直接让人黑人问号。不过新人没有负担,实际上新 React,新人比老人更容易上手)
但是 Vue 作为一个框架,应该和老版本彻底划清界限,生命周期删除掉,老版本 api 全部删除,别给老代码提供机会,社区生态会有更好保障(框架 api 和库不同,他不会直接做陈列,很多 api 隐藏很深,同时面积也会大得多)
这次大版本更新有内置 csp,依赖注入(老版本依赖注入无类型推断支持,无完全编程能力),实际上架构是有翻天覆地变化的,ng 15年的版本更新也是因为这个原因,直接断代更新
如果 Vue 不这么做,未来生态状况会很让人担忧,如果生态和 React 一样乱,代码质量甚至比 React 还要难以控制,是否会丢失核心竞争力?
不过好在,有 script setup 作为补偿,目前看趋势是很好的
5. class 支持不全
如果 Vue 的响应式变量调度无法拆分,那么直接给 class 会不会更好?作为对 React 词法逻辑能力的增强,不上 class 总归有点奇怪,因为面向对象就是词法逻辑发力的地方,自动生成文档,自动生成 uml,自动分析,测试友好性,架构友好性也更强
比如公共属性默认 reactive,getter setter 默认 computed,带装饰器方法作为 watch,我试过很多次对 Vue 进行 class 改造,但是无论是实例化加 reactive,还是装饰器进行处理,后果都是必须跳过 constructor 才能有初始化能力,如果真需要支持,还是得框架本身来进行支持
如果本身有响应式传递,却把 ref value,watch 响应式断裂 等问题引入进来,为什么不直接上 class 呢?
不然为了架构能力,人们选 ng ,为了 csp 和灵活性,人们选 react,那么选 Vue 的意义又是什么?
但是 Vue 还是会比 React 更加热门
哈哈,因为 Vite
由于 React 和 Vue 的用户高度重叠,其实真正的竞争根本不在 RV 内部,由于 Vite 直接带来的纯粹的性能提升,我们以及现在越来越多的 React 或者 多个框架使用者,都直接采用了 Vite
事情变得有趣起来
或许 Vue3 并没有那么令人满意,但是框架是可以慢慢优化的,构建工具却是一旦选择就会长期霸占市场
所以其实 React 并没有赢,因为前端框架其实并非核心竞争力,只是前端程序员内卷的平台,构建工具才是关键
一个聪明的开发者,现在都是写着 react,然后没事 create @vitejs/app 看一下,Vue 好用了,呵呵,二话不说就转过来了
都没啥根本性差异,纠结那些细节有啥意义?相当于影院都是 Vue 家的,我们纠结哪部电影好看,也就只是闲聊罢了?