左手粘着Vue右手舞着React
作为前端开发工程师,当我们左手拿着 Vue,右手拿着 React,关于它们的种种,其实我们都应该是了然于胸的。
宏观概念
拿到一个前端框架,我们更应该如何去看?肯定不是一头扎进 api 的调用方式,也不是一头扎进源码的海洋。我们应该有对比的看,和你熟悉的一个框架去对比。
众所周知,前端接触最多的是浏览器,浏览器也是面向用户最直接的宿主环境。我们的页面,不管是 SPA,SSR
在浏览器呈现出来的,就是 html/css/js。所以我们以结果触发,首先看,这个框架是如何生成 html/css/js 的?
我们先掌握这个宏观概念,再带着疑问去看细节。
所以,对于 vue 和 react,我们从两点切入:
- 数据驱动视图
- 组件化
数据驱动是这两个框架的相同点。
组件化也是这两个框架的相同点。
这两点是核心思想,而他们之间的不同,就是在实现这两个核心思想时选择的策略不同。
两个人的目的都是罗马,一人走的是水路,一人走的是陆路
组件化
我们从组件化开始,所谓组件化就是拼凑页面的方式,搭积木。我们要做的就是优雅的拆分和重组
回到 hmtl+js+css 的开发模式,假设我们手上拿着这三个文件,
文件的结构是这样的:
上
中
下
如果我们要实现组件化?怎么样去拆分和组合这个文件呢
- 函数组件
- SFC
React 选择的是函数组件
我把上中下,看成三个函数, 三个 function,html、js、css 都可以写在这个 function 里面
上function
中function
下function
Vue 选择了 SFC(虽然它也支持 JSX)
我把上中下,看成三个文件,三个文件拼凑成一个文件。html、js、css 都在各自的文件里面
上.vue
中.vue
下.vue
这里两者的设计思想其实已经初现端倪了。
一个是用 function 去组合文件。
一个是用文件(模版)去组合文件。
这也就是 vue 的写法更让人容易接受:用文件拼凑的一定是文件。
- JSX
- options api
单向数据流是两者实现的默契选择。
组件化我们先告一段落
数据驱动
UI 我们通过组件化开发的方式写好了,接下来考虑怎么去实现页面交互,展示页面数据了。
两者都是通过数据的变化而变更 UI,但是两者实现的差别,正是因为各自组件化实现的不同而导致。
react 基于 function,那么很自然,要更新视图,我重新执行当前 function 去进行局部刷新,很合理。
vue 基于 SFC,那么要做的事情就相对有点多(当然是 vue 去做,不是开发者去做)。首先需要编译.vue 文件,进行数据拦截/代理,收集依赖,数据变更的时候触发更新。
这个实现数据驱动的方式不同是核心差异。后续的不同都是基于这个点去延伸的。
react 并不知道什么时候去刷新,因为它没有数据拦截代理,依赖收集。你要刷新,你就 setState。
(这里可以拓展 shouldComponentUpdate)
vue 不同啊,因为它基于模版,它啥都知道啊。所以性能方面,它有的放矢,相比之下有点优势。
正是因为手中有模版,Vue 能在编译阶段做点事情,什么静态提升,类型标记。
这里可以拓展(react 的 fiber)
有了以上这些宏观的概念,我们再跳出来看细节,是不是看到的东西就不一样了。
vue 的 value
vue3 中,这大概是被吐槽最多的地方,拿一个值,需要 count.value 这种方式。
因为 vue 为了实现数据拦截/代理,但是 js 中基本类型是无法通过 Proxy 去代理的。所以妥协策略就是自己再包装一层。
React 的 Class 组件和函数组件
基于 function 的思想去理解 class 组件,那么就能理解基于 class 的能力,它是如何去保存状态,去实现数据流,去构造高阶组件等。
同样也不难理解,基于 function 的逻辑复用解决方案(作用域和参数)
Mixin -> Hoc-> render prop
hooks 的出现,可以简单理解为在函数层面,怎么去规避或解决 class 组件写法带来的问题。函数层面的状态缓存,在 js 中想到的是啥?那当然是闭包,hooks 确实也是利用了闭包来实现的。
个人理解主要有两点:
一:hooks 基于函数式的复用,不会和原来的 class 复用一样,有一堆的 wrapper,也不会改变组件层级,因为它仅仅是函数调用函数
二:淡化生命周期的概念,既然是函数,那就一定有执行顺序。hooks 利用链表来实现每个组件 hooks 的顺序调用(这也就是为什么 hook 要在顶层,不能在一些条件语句中)
以上,你也就不难理解什么叫自定义 hooks:想要复用一个东西,那我在要用的地方都调用同一个函数,这样就 OK 了。
结语
正所谓万变不离其宗。
当我们看到 Vue 的新特性或者 React 的新能力的时候,我们不应该只感慨:好家伙,又要学。
其实我们更应该从本质看现象:哦?这个功能是为了优化什么呢,是为了降低什么心智负担呢?
因为我们心里有两个抓手(函数是一等公民)和(模版与代理)