Angular、React、Vue三大框架逻辑复用横评
授权转载自:江湖术士
https://zhuanlan.zhihu.com/p/208249521
其实这个文章早在16年左右有感于 ng 的学习就想写了,但是却发现,除了 ng 以外,当时的 React 和 Vue 都缺乏简单有效的逻辑复用方案,不过这也引导我将 React 和 Vue 都学习了,对自己的职业也有了积极的意义
一个 nger 找工作有多难,你们知道么?但是标榜 vuer/reactor 之后,真的是一投一个准,个中滋味可以自己体会,我当然还是建议 nger 学学其它框架,你如果真的理解 ng,其它框架的学习都是降维打击,比如 Vue composition 一发布,你看一眼就知道最佳实践应该是什么样子,框架没有高低之分,学 ng 的那些痛苦一定是会有回报的,心思活跃一点就好,不要死守着一个平台
前端反内卷还是很坚定的,你看 java,内卷到不行,动不动就问服务治理,netflix 标准啥的,DDD,SOA,微服务张口就来,设计模式少背一个就被批基础不牢,然后给个5,6000工资,你看我们前端多好,理解面向对象和纯函数就能拿高工资
自嘲归自嘲,就目前的情况来看,前端的好日子应该是到头了,React Vue 都有了自己的逻辑复用方案,这时候不妨来一个横评,大家除了了解各个框架异同以外,也能窥探一下整个行业的发展方向
响应式
ng 首先实现逻辑复用不是没有原因的,并不是说 ng 的开发者比其它平台的厉害多少,这个尤大已经有过表述,最大的原因在于,ng 的响应式对象,直接采用的微软出品的成熟库
rxjs —— angular
配合 rxjs 使用的 zone.js 也是事件驱动响应式的典型,这个和 React,Vue 的方案有所不同,在数据量大的情况下性能非常强,但是在 “多 watcher 少量数据”下性能要很弱,这也使得最佳实践的难度非常之高 —— 业务逻辑用极限函数式开发,无变量,无状态,无watcher
这是 Angular.cn 入门教程英雄指南的一个代码片段,你能感受到16年初学习 ng 时我的绝望么?它只是个入门引导,但是我认得它,它不认得我啊!想象一下,Vue 讲模板语法的那一章突然来个这个,你是什么感觉
而且,因为事件驱动和 zone 的暴力代理,某些情况下需要 runOutside 和 changeRef,要知道事件驱动费脑,数据驱动费手,选择这个方式必然推广困难,你想想,写业务是加个标识位简单,还是加个管道简单?
普通程序员接触 rxjs 也很有可能是后来 react 平台推广的结果,多个 React 工具文档出现了 rxjs 导致的?后来出现了很多用于学习 rxjs 的工具,比如:https://reactive.how/,即便有那么多的视频讲解,真正保证学会 rxjs 并用好的的,应该也只是极少数人
这东西和ramda,都属于成年噩梦,最大的问题是,废了老大劲学的东西,实际开发中却很少用到,这种落差感也是非常的大,后来我知道是自己用法的问题,尤其是 react hooks 出来之后比较 react 的用法,才更清晰的明白最佳实践应该是怎样的,不过在缺乏文档,缺乏引导的情况下,你确定你知道该怎么做?
Memorized hook —— react
其实很简单,就是一个数组结构中的 getter 和 setter 的控制反转 monad:
const [value,setValue] = useState('')
平心而论,这个结构是真的太直观了,响应式本来是啥,就是 getter 和 setter 啊,呐,你看,getter 和 setter
当然,拆开这两部分并不只是为了直观的原因,还有一个很大的原因是,React 平台死守不变性原则,也就是无赋值,无变量,保证函数式开发体验
这也是 为何 大对象建议业务上使用 useReducer 的原因,也是死守不变性的结果,当然,你牛你可以自定义 hook
这个函数式开发体验并不极限,比 rxjs 那种调用链管道模型要简单(React 程序员要有清晰的认识啊,函数式不是用来内卷的工具,至少碰到其它管道框架的时候得稳重点),当然也有死守管道风格的框架,cycle,那就更反人类了,这种东西用在金融系统,武器系统的开发可以,用在前端意欲何为?我是真的认为这个东西是大炮打蚊子,ng 毕竟还有 baas 服务,有前后端同构的考量,cycle 这个真的是存粹的兴趣爱好了,发扬极客精神,另外自定义 hook 也可组成管道,这时 react 的极限函数式风格就来了,大家可以使用 ramda 封装试试
不过 rxjs 还有一个好处,在 vue 没有逻辑复用的时候,vue-rx 给我开了个逻辑复用的口子,让开发效率提升了非常多,你看,我就说东西都不会白学的嘛,当然,rxjs 的侵入性很强,rx 配合谁都是 rx当主角,其它技术栈当配角
说到 Vue,其实就是无“不变性”要求的 React,这么说有点粗暴哈,但是对于一个之前的 nger 来说,Vue 和 React 的差异真的只是写法上的差异,原理上并未有太多区别
但是思想上确实有个重大的区别,那就是:
为啥要追求函数式?追求更好的可调式性?前端有那么多业务逻辑么?
问问后端程序员,把逻辑放在前端是个很好的设计风格么?
当然这是在不考虑前后端同构语境下的想法,ng 引入一个 module 直接支持ssr,next 只是 react 的轻度再封装,nuxt 可是要复杂得多,也和这个思想有一定关系
不过这种想法细想一下,有没有道理?从业过程中我发现很多开发人员对 Vue 平台有意见,固然有文人相轻的因素在里面,但是好好想一想吧,那些模式用在 后端 是不是更有意义?
所以直接上 proxy,setter,getter 合二为一,完成响应式:
Proxy —— vue
直接一把梭,管他的,用就完事儿
vue 如此火爆,不是没有原因的,面向简单编程,因此主要的响应式,什么概念都可以丢掉,左手 ref,右手 reactive 打天下:
const ref = useRef(null)
const data = reactive({xxx:1})
尤其是新版本代码风格,上手成本直线下降,个人觉得 vue 新版本发布才是真正宣告前端进入新时代的标志
组件语法
Angular
Angular 的响应式需要配合管道使用:
这里有个问题,如果对象需要进一步操作,复杂度稍稍有点增加:
没有计算属性的概念,有的只是管道复用:
const origin$ = new BehaviorSubject('')
const init$ = origin$.pipe(res=>res+'inited')
副作用在 subscribe 处理:
// 普通
click$.subscribe(...)
// 最佳实践认为,副作用应该得到控制,比如请求是个新的流
const data = click$.pipe(switchMap(()=>request('....')),map(...))
// 而 data 又用于视图
但是因为是管道,副作用直接全部在视图处理,这也是极限函数式处理业务的优势,哪里输入,哪里输出安排的很明白,当然,这难度也是够你喝一壶的
独门亮点,单独的模板作用域和模板引用变量
比如你需要一个动态组件,声明一个模板引用变量:
注意,这个 content 是不需要在组件中声明的,直接在模板标记,就可以到处传值,这个和 Vue 的区别很大,Vue 的 # 只是 slot 语法糖,传递数据用的,在这部分内容的复用上要弱很多
弱点or亮点?指令封装 spy
ng没有直接提供生命周期的逻辑复用,而是需要你去实现生命周期 spy 指令,比如官方示例:
// Spy on any element to which it is applied.
// Usage: ...
@Directive({selector: '[mySpy]'})
export class SpyDirective implements OnInit, OnDestroy {
constructor(private logger: LoggerService) { }
ngOnInit() { this.logIt(`onInit`); }
ngOnDestroy() { this.logIt(`onDestroy`); }
private logIt(msg: string) {
this.logger.log(`Spy #${nextId++} ${msg}`);
}
}
// props 改写,用流
@Directive({selector: '[mySpy]'})
export class SpyDirective implements OnInit, OnDestroy {
@Input() change$:BehaviorSubject('')
ngOnInit() { this.change$.next(`onInit`); }
ngOnDestroy() { this.change$.next(`onDestroy`); }
如果实现为一个流,那么就可以如下使用:
这样就可以把生命周期逻辑全部写在服务中了,好处是指令更加灵活,坏处是,很多时候默认没有,程序员就不会去使用,导致生命周期逻辑不进行封装,增加开发和架构难度
这一点上可以见仁见智了
React
Jsx 的优点当然不是大家以为的 ts 支持,很多 react 程序员喜欢拿着 jsx 和 vue2 的 template 比类型支持,这很容易让人笑掉大牙的,毕竟 ng 都出来五年多了,但凡用一下也不会有这样的想法
但是有一点 JSX 的优势是非常大的,那就是上下文清晰:
典型的函数作用域,甚至不需要思考,哪个变量属于哪个对象一目了然,这是单独封装模板甚至单独拆文件的框架很难得到的体验,比如 vscode 平台有个 ngSwitch 工具,那就用的很无奈,注意,Jsx 的最大优势是这个——充分利用函数作用域,以后看到 ts 我都懒得反驳了,完全是八竿子打不着的东西
另外还有 jsx element 的灵活性,这个很直观,不用赘述
但是 Jsx 不是还有劣势么?可读性?
有逻辑复用之后,组件没有业务逻辑,好的方案一个组件函数中只做变量填空,Jsx 的劣势一下子被抹掉,忽然有种 Jsx 春天来了的感觉,具体情况如何还需要看最后社区的选择,尤其是 Vue 这种同时支持两种写法的方案
不过,React 的 Hook 却在一个地方降低了可读性
我怎么知道你这个变量是响应式的,还是非响应式的?毕竟你还有个 useRef 在那里呀,对象也可以直接写啊~
{value}
就这样的代码,你怎么知道 value 是不是响应式的?相比之下,Angular 管道显示声明 | async,响应式变量也有命名标准,Vue 有 isReactive 等工具(当然作用也有限),React 这里就很难控制了
所以建议不要将 hooks 拆开,作为整体声明和传值,带上响应式标识$也不是不可以:
const value$ = useState('')
{value$[0]}
当然这个数组取值也是很难受,尤其是遇到依赖数组的情况,官方不做这种推荐是因为 ——
函数式体验
对,还是他妈的函数式体验,因为在函数式开发中,状态也是函数,有点拗口哈,就是没有存储的“量”,即使是不变量,也是返回确定数据的函数 Identity
唉,学院派简直就是西装暴徒!用的人真的好无奈啊
副作用在 useEffect 处理:
useEffect(()=>{
...
},[...])
因为不是管道逻辑,没有流那样对副作用限制得那么狠,显然这个 useEffect 最好是不要用的,因为副作用理应得到控制,但是这个标准以这种写法实现起来实在是太难,官方都只能给你开个过程式处理副作用的口子
独门亮点 —— 弱化生命周期
这个是真的亮点了,想想你需要生命周期么?你其实并不需要生命周期啊
整个应用拢共就视图变化和状态变化两个,effect 和 layoutEffect 还不够么?
当然这一点 ng,vue 现在也一样,不过有意思的是,react 用空依赖数组做首次更新,用返回值做析构,api 精炼了好多
再看看 ng 的 spy,其实原生这种 api 应该是会更好的,尤其是 rxjs 配合 生命周期
理论上来说,生命周期其实都是不需要的,响应式就让他自己触发自己变化好了,为啥要解开它,watch 它?你看 ng 的 rxjs ,你只用写一个个管道就够了,函数式响应式处理业务,没必要去关心具体的状态
这个真的想给 React 一个大大的赞,等于是强制前端开发进化+内卷,接受函数式开发更进一步,咦,为啥强制内卷我还挺开心?
弱点 or 亮点?—— 依赖数组
他妈的依赖数组!
所有用 React 的人不信你没骂过,没办法,死守不变性嘛,没依赖就不纯了
他妈的不变性!
这个玩意儿是真的恶心,写不写是一方面,你别再代码里给我报一长串 warning 啊,好难受啊,太不近人情了
所以看你狠还是我狠,大不了老子不写 effect,结果发现 useMemo 也要写,唉~
React 可以说是强迫症的最爱吧,其实完完全全的函数式用于生产环境真成问题,否则haskell早就一统后端市场了
一般来说函数式在处理运行时业务逻辑更有效,但是数据结构,初始化等问题,还是面向对象更为擅长一些,这也是 Angular 为啥组件服务用 class 组织,业务逻辑用 rxjs 的原因,各取所长嘛
Vue
面向简单编程
模板帮你取value?
{{test}}
setup(){
const test = ref('')
return {test}
}
这是亲妈风格的 api 封装啊,这已经和原理相悖了,proxy 对象封装,只有 test.value 才能操作数据,为啥写的时候要 test.value = xxx, 用的时候就 test 了呢?
只能理解成亲妈式封装,门槛能降一点是一点
这种思想其实在 Vue 的设计中随处可见,用户要啥,就给啥,一切从用户体验出发,还是那句话,前端能有什么业务逻辑,难道没用设计模式,支持不变性,就能让你操作数据库了么?
怎么简单怎么来,composition 状态复用只有两个 api,不变性 api ref,和 深层可变 api reactive
哈哈,反着来了,因为有getter,setter,所以 ref 等同于 React 的 useState,而 reactive 等同于 React 的 useReducer,仔细想想是否如此,因为不遵守不变性了(写法上),setup 只运行一次,所以类似 React 的 ref 就没了
只运行一次,所以很多问题得到了简化,按官方的说法就是:
一般来说更符合惯用的 JavaScript 代码的直觉;
不需要顾虑调用顺序,也可以用在条件语句中;
不会在每次渲染时重复执行,以降低垃圾回收的压力;
不存在内联处理函数导致子组件永远更新的问题,也不需要useCallback
;
不存在忘记记录依赖的问题,也不需要“useEffect”和“useMemo”并传入依赖数组以捕获过时的变量。Vue 的自动依赖跟踪可以确保侦听器和计算值总是准确无误。
直觉这个东西说的没错,函数式就是反直觉的,函数式基于范畴论是拿给你计算的,不是那给你撸的,但是这句话总感觉差点什么,这么说就对了:
更符合过程式 JavaScript 的直觉
其它问题也都是函数式风格的问题,但是函数式的优点也是有很多的,最后看你适合什么方案,比如 Vue 的 vca 方案,就几乎和 React 无差别了:
// Before compiling
import { ref } from '@vue/composition-api';
const Hello = (prop, ctx) => {
const state = ref('Hello World!');
return () => (
{state.value}
);
};
// After compilation
import { ref, createElement as h } from '@vue/composition-api';
const Hello = {
setup: (prop, ctx) => {
const state = ref('Hello World!');
return () => {
return h('h1', state.value);
};
}
};
当然,Vue 的 Jsx 用法和 React 有很大差别,比如属性绑定,render 有多个属性,详情间官方文档,其次是参数类型提示问题,这个还需要时间来解决,但是这个的工作量应该是非常大的
模板语法上没啥亮点,功能性和 Angular 相比差了非常多,vls 的使用并没有 als 方便,但是,Vue 能用 js,ng 早就放弃了 js,高下立判,很多人就是接受不了ts,
独家优势 —— 动画
原生集成了一个比较简单的动画方案,包含状态过度以及显示动画,很多人觉得这有什么大不了的,ng 也有啊,很抱歉,我在15年底第一次看文档的时候,ng 的动画实现方案,把我的头弄炸了
React 也需要第三方库来做状态动画,当然,也有人说,有逻辑服用,直接写个 use 不也能实现
有这些想法的人,是个合格的程序员,但是不是一个合格的产品经理,可能切中了技术要领,但是没有切中市场要领
对于很多初学者来说,我不想知道你有什么新技术,也不想知道你的封装方式有什么优点,我就想看你简不简单!
Vue 这种加 class 名的方案,就是很好的,很简单的,初学者也能写出良好交互体验的网站,前端的重点真的在业务逻辑上么?想多了,前端的重点就是在炫目的交互效果和UI效果上的,其它的都只是附加的东西(非前后端同构,非跨平台的纯前端项目),很多人都低估了 Vue 在这方面的竞争力
大家可以自行比较一下ng和vue的动画方案:
Angular - Angular 动画简介:https://angular.cn/guide/animations
进入/离开 & 列表过渡 — Vue.js:https://cn.vuejs.org/v2/guide/transitions.html
也可以对比一下 React 第三方库 ant motion:
Ant Motion - Ant Design 的动效规范与组件:https://motion.ant.design/index-cn
大厂有包袱,他们做的东西不仅要满足实际使用者,还要满足同行和学界的挑剔目光,因此很多好用但反模式的东西不敢去做,我们的话无所谓,干的就是搬砖的活,端着干啥
绝大部分的人工作并不是造火箭,普通人改变不了世界,快速完成从零到一,也是一种实事求是的态度
应用架构
这个不用说了, Angular 第二,没人敢说第一
确实有复刻 Spring 相关技术栈的影子,Nestjs也是如此
但是这个架构确实好啊,确实牛逼啊,大型的成熟项目后端,哪个不是 SOA 打天下的?
15年 Angular 主推 SOA 的时候,争议是真的大,那个时候 React 和 Vue 连成熟的逻辑复用都没有,这边就 IOC,依赖注入了,社区之间的谈话谈话都是鸡同鸭讲,语言都没统一, 你说函数式响应式,他说纯函数,你说面向业务DDD,他说你说的都是后端概念,你说类型完备,他说Vue怎么就不能用Ts了?无意义的争吵太多
了解那段时期氛围的人都知道,确实很浮躁
现在好了,相关说明和解释出现在了 React 和 Vue 的官方文档,语言终于能够统一了
provide/inject , useContext/Provider,都已经成为主力 API,人们开始了对 Redux/Vuex 有没有意义的争论,类似当年ng社区对ngRx的争论,摘要一下哈:
redux 模式是纯函数?rx 操作函数就不是了么(ng)?useState 就不是了么(react)?vue 平台不要纯函数(vue)? 要保证单一数据原则?providedIn:'root' 就不是单一数据了(ng)?app provider 就不是单一数据了(react,vue)? 方便调试,生命周期都没有你怎么方便调试?找出了dispatch还要去找生命周期,不闲得慌么? 跨组件数据传递?你在抹黑这次更新 封装方便团队协作?逻辑都封装不到一起,协哪门子的作,用 cdk/ahooks,能和 阿里/谷歌 协作 状态本地化?useLocalStorage 不香? 服务端状态保持?rxjs 的 retry,timer ,ahooks 的 manual, pollingInterval 不是吃干饭的
历史的问题就不用再纠结了,可以先看看 Angular 的架构强大在哪里:
类型完备
只支持 Typescript 并保证 99% 的可访问 api 都有类型推断,这点React就望尘莫及了,只给接口和泛型,不给类型推断,数据和类型声明分离,Typescript 在不将类型看作函数进行二次封装的情况下,使用体验非常差
而且我相信,React 本身就讨厌 Typescript,原因很简单,对,没错,就是函数式体验~
又他妈的函数式体验
函数式开发中类型的作用和功能与面向对象不同,类型更多是起到校验作用,类似于一个运行时的测试机制,这点可以去看 Car Baaz 的访谈:
https://www.techug.com/post/haskell-production-retrospective.htmlwww.techug.com
压根就没有集成数据结构的概念,要是按照用 ng 的类型使用方式去用 React,怎么用怎么别扭,所以需要你二次封装,相当于编写了一个 运行时测试 ……
但就我看过的代码,大多数 Ts 版本 React 开发者,没有这个意识,而且,React 这种用法,结合Flow才是最合适的,运行时测试和编译前校验,区别非常大,也是因为社区追捧 Typescript 吧,被裹挟了
自动依赖注入
Vue 也有依赖注入了,而且用法非常简单,但是并没有实现完全的 IOC,需要手动 Provide,Inject,还需要加 Token(Symbol),和单独的类型声明
Ts 语境下,这部分封装成 Class 可以优化
import { Ref, ref, provide, InjectionKey } from "vue";
export class TestData {
test: Ref;
constructor() {
this.test = ref("init");
}
change() {
this.test.value = "fuck";
}
}
export const Token: InjectionKey = Symbol();
export default {
name: "App",
setup() {
const testData = new TestData();
provide(Token, testData);
return { testData };
},
};
Class 的作用主要是为了将数据的声明和类型的声明集中,提供初始化入口,方便计入 InjectionKey 的泛型,你可以看到,还是有 new,如果要好一点的类型体验的话
这个 new 就很烦躁了,面向对象,new 是万恶之源,严格来说这并非强类型语境下的依赖注入,IOC并未完全实现(初始化逻辑未接管)
但是 ng 就要简单多了,一般情况下:
构造器参数声明,即完成注入,当然啦,这也有 Vue 的无奈,原因很简单,这样的 IOC 方案需要装饰器加类型反射(reflect-metadata typeName:)才能实现,而 Vue 还需要将就 Js 使用环境:
但是这样的话,架构扩展性和 ng 相比就有很大差距了,不过这不妨碍 Vue,原因很简单——你能在前端做出微服务集群来,算我输,前端没有强业务逻辑,用不到牛刀杀鸡——当然这个问题见仁见智了
可配置Module
一般情况下被视为花活,但在 google adword 这样的应用中被视为刚需,那就是可配置 Module
将一个服务包含依赖以及相关视图打包,用于优化编译器
比如,你要用 Angular CDK 功能,直接在需要用 cdk 的 module 中imports cdk 某个功能 就可以了:
import { DragDropModule } from '@angular/cdk/drag-drop'
…
@NgModule ({....
imports: [...,
DragDropModule ,
…]
})
然后这里面有的组件,指令,服务啥的,都随便用,大门敞开,不需要像 Vue 一样,import Component 再 声明 {components: { someComponents},filters, ... }
其实就是耗费开发的时间,节省使用的时间
同时,指令真的好用,React 技术栈真的好可惜,没有这个功能呢,高阶组件再怎么说也是封装,封装和附加的区别还是很大的,就和装饰器跟继承的区别一样
其它的还包括他的多语言架构,简单的ssr同构,baas同构(angular/firebase),以及,以后系列文章会讲到的,微前端 —— 利用module封装其它技术栈代码,生成shadowDom,当然,这个特性还包含 Angular 的样式封装特性,从编译源头解决 shadowDom 的同构问题,还有开发时cli辅助,路线图等等非常工程化的特性
数据结构用极限面向对象解决,业务逻辑用极限函数式解决,什么都走极端就对了,下限和上限都非常高,弱点就是容易曲高和寡,应者了了,前端程序员应该去学习,但是生产环境使用的话谨慎吧,毕竟是前端,明白自己定位最重要,那些概念学了之后,用在nestjs上搞微服务多好?
Nest.js 中文文档docs.nestjs.cn
前端的数据量和业务量,除非你真能搞个 adword 一样量级的创收项目(稳定性要求,多样化需求,全球化,交易服务等会让业务复杂度直线上升),不然真的**有牛刀杀鸡的嫌疑,**喜欢端着不是件好事,技术的选择应该契合业务,而非业务契合技术,大部分情况下这个架构更适合后端的业务量和数据量,所以 nestjs 的热度逐年上涨,甚至有成为Java程序员逃避死板代码的避风港的趋势,也算是意料之中
Angular 可以作为一个相关概念的学习基地,方便你很快地切换到后端开发,同时也可以引导你了解项目架构的最佳方案应该如何,方便你自己搭建其他平台项目的架构,实际使用的话,能保证团队成员意识形态一致,有较高的追求,可以一试,但也仅仅是一试,有点脱离基本面了,效率,人员等都是没有保证的,很多国内公司切换过 angular,又切换回来了,不得不向现实低头
不过不用笑 Angular,React 一样有点脱离基本面,只是说普通人很难写出最佳实践而已,简单易用还是有保证的,这点比 Angular 强
但是,过程式一把梭,面向对象只要求你想清楚,函数式要求算清楚啊!我们这些大学离散数学只有60分的学渣,怎么搞定态射演算啊,只记得住一个结合律,其他啥都忘了,当然后面有补课,过程也是痛苦万分的,现在又在遗忘的边缘试探
而且函数式无所谓架构,自底向上,一步步累进封装,保证灵活性和测试完备,理想非常丰满,现实也是骨感得很,要知道函数式基础不牢固,一个点坏掉,这个系统都危险,要是架构部分的需求变化,面对那一坨陀错综复杂的函数,很容易让人失去信心的
简单来说:
函数式自底向上:我搞了一堆功能和函数,都有完备测试,看看能做点啥
面向对象自顶向下:我要做一个系统,它由以下抽象类组成……
所以到头来还是用和Vue一个封装层级的框架完成开发,类似 umi,才能满足生产环境的需求,变换为自顶向下的开发模式,这实际上是反函数式的
这时候不变性,纯函数成了累赘,有没有人计算过这个纯函数和不变性到底节省了多少测试成本,优化了多少性能?再问尖锐一点,有写红蓝测试的习惯么?测试有为函数式开发做配套支持么?技术追求和实际需求是有断代的,更不要说之前无逻辑复用还能用函数式用的那么嗨,样板代码一大堆,接手的人望洋兴叹,有技术主导需求的嫌疑,并非一个好的企业架构
所以 React 存在和 Angular 一样的问题
另外,逻辑复用应该算个大更新,应该用很大的魄力回炉重造,Angular 有这个魄力划清界限,但是 React 没有,还存在很多历史问题没有解决
要知道很多 Angular 工具和 React 工具都是在解决框架本身的问题,很多 React 工具本身就是用来解决逻辑复用,或是强制自己实现逻辑复用开发出来的,比如大堆的第三方库新版本已经没有意义,redux,redux-thunk,各种工具库,在新版本语境下已经不知所谓了,还会成为历史遗留问题继续产生作用,既限制开发者,也限制框架开发
当然,函数式天然和架构不沾边也是问题之一,你见过什么大型工程项目是存粹用函数式搭建的?有数学完备支持的,理想的无bug系统,终究只是理想,现实世界是充满复杂性的,Angular尚且可以回退到promise,非rx使用方式,React这个函数式一把梭,真的有些强人所难了,happing hacking,但是普通开发者不是 hacker,没必要陪着你一起追求美好未来吧?
喷了一通,如果让我一个人做一个中小型项目,一个人做一个大型项目(基本不可能哈),我还是会选择 React 和 Angular,怎么了,我就是追求美好未来的三有青年呀~
那么接下来就是历史和市场的选择,前端代言人了 ——
一把梭,面向简单,文档支持完美,循序渐进,前端内卷缔造者,Vue
Angular,React 还会纠结逻辑复用版本的接受度问题,Vue的方案,真心没啥负担
你想想,上一版本你还要学单向数据流,还要学响应式原理,还要用 Vuex , Vue.set 啥的,更早还有 event bus,实例响应式数据等等,api面积真的大
现在:ref,reactive,provide,inject 最多加上 mounted 和 watch,6个api打天下,啥单向数据流,直接改了不就完了,你跟新手说单向数据流,可能会被当成 xx,实际上也是,setter在父组件或者服务中,压根没有违背原则,等第三方逻辑库流行,就是完完全全的傻瓜操作了,什么函数式,面向对象,都是后端的概念!
你想想,比你知道的更少的新手,写东西还比你快,难受不难受?纠结不纠结?
内卷不内卷?
在 Vue 支持 逻辑复用之后,前端的好日子终究还是到头了,大量新人会涌入,然后抢占市场,压缩开发者薪资
而前端如果不走出 逻辑少,数据少 的泥潭,是不会有未来的
目前几个方向可能寻求突破
前后端同构,BFF,作为视图服务,成为微服务架构中的一环,不过这个概念很难灌输给 cto
2. 期待新的端到端通讯,成为边缘云中枢,这个很有可能实现,不过短期很难,而且,届时 wasm 可能会抢占传统前端市场
3. 利用前端技术栈在 faas 中的优势,自己创业,或者加入创业公司推广这个吧,成为云服务厂商的帮凶
4. 死守技术栈干嘛,转栈做 devOps 啊,这个才是热点,议价能力强
借这个时机,抖音再投几个广告教授 Vue3 的课程,这个过程不知道要被加速多少倍,被资本家剥削真的太难了
所以你要是真的热爱技术,跳出资本循环,敢于承担风险,做自己吧~