Vue2 vs Vue3 vs React vs Hook(类编程vs函数式编程 )

一些日常业务中,对vue2 vue3 react hook等的理解总结。分为3块对比

  1. Vue2 vs Vue3
  2. 类编程 vs 函数式编程 (vue2 -> vue3 / class -> hook)
  3. React vs Vue

Vue2 vs Vue3

  1. vue3是monorepo架构,更好按需加载,使得核心库变得更小(加载 执行都变快)
  2. vue3更快的update的速度
    1. 缓存 模板上元素绑定的事件 ```jsx

import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from “vue”

export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createElementBlock(“div”, { id: “app” }, [ _createElementVNode(“button”, { onClick: _cache[0] || (_cache[0] = (…args) => (_ctx.handleClick && _ctx.handleClick(…args))) }, “戳我”), _createElementVNode(“button”, { onClick: _cache[1] || (_cache[1] = () => { _ctx.console.log(111) }) }, “戳我”) ])) }

  1. 2. **增加对静态节点的标记,相当于缓存静态节点**
  2. ```jsx
  3. <div id="app">
  4. <h1>我是静态节点</h1>
  5. <div>{{name}}</div>
  6. <div :class="{red:isRed}">摸鱼符</div>
  7. <button @click="handleClick">戳我</button>
  8. <input type="text" v-model="name">
  9. </div>
  10. // 打包后
  11. import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
  12. export function render(_ctx, _cache) {
  13. return (_openBlock(), _createBlock("div", { id: "app" }, [
  14. _createVNode("h1", null, "我是静态节点"),
  15. _createVNode("div", null, _toDisplayString(_ctx.name), 1 /* TEXT */),
  16. _createVNode("div", {
  17. class: {red:_ctx.isRed}
  18. }, "动态节点", 2 /* CLASS */),
  19. _createVNode("button", { onClick: _ctx.handleClick }, "戳我", 8 /* PROPS */, ["onClick"])
  20. ]))
  21. }
  22. // 动态节点注释表
  23. TEXT = 1,// 表示具有动态textContent的元素
  24. CLASS = 1 << 1, // 表示有动态Class的元素
  25. STYLE = 1 << 2, // 表示动态样式(静态如style="color: red",也会提升至动态)
  26. PROPS = 1 << 3, // 表示具有非类/样式动态道具的元素。
  27. FULL_PROPS = 1 << 4, // 表示带有动态键的道具的元素,与上面三种相斥
  28. HYDRATE_EVENTS = 1 << 5, // 表示带有事件监听器的元素
  29. STABLE_FRAGMENT = 1 << 6, // 表示其子顺序不变的片段(没懂)。
  30. KEYED_FRAGMENT = 1 << 7, // 表示带有键控或部分键控子元素的片段。
  31. UNKEYED_FRAGMENT = 1 << 8, // 表示带有无key绑定的片段
  32. NEED_PATCH = 1 << 9, // 表示只需要非属性补丁的元素,例如ref或hooks
  33. DYNAMIC_SLOTS = 1 << 10, // 表示具有动态插槽的元素
  1. 类编程 到 函数式编程 (vue2 到 vue3)
    1. 组合式api:大型应用中,逻辑可以组合在一起,会更清晰好维护
    2. 某些方面变得更加手动而不是自动。
    • 在vue2中,每个组件都会被自动注入route和store,vue3变得可控
    • 在组合式api内,可以像react一样,写多个hook组合,比如 ```jsx // 如果是vue2的话,数据只能放在data里,生命周期钩子只能有一个,多段无关逻辑 都耦合在钩子里

// 以下是vue3,组合式 const aa = ref(1) onMounted(() => { console.log(aa.value) }) watch(…)

const cc = ref(‘’) computed(…) onMounted(() => { console.log(‘处理cc的逻辑’) })

  1. 4. 更好typescript支持
  2. 4. 响应式核心api Object.definedProperty -> **Proxy** (**更加彻底的监听**)
  3. 4. vite
  4. 1. 基本原理是浏览器支持esm,不过需要高版本浏览器,chorme都要61以上,支持动态importchorme63
  5. 1. 热更新和重新启动都非常快,并且热更新的速度不会随项目变大而变慢
  6. 1. 第一次构建还是需要时间,之后就很快。第一次需要依赖预构建 用的esbuild(速度很快)
  7. <a name="9c19af3e"></a>
  8. ## 类编程 vs 函数式编程
  9. | | 类编程 | 函数式编程 |
  10. | --- | --- | --- |
  11. | vue | vue2 | vue3(setup内) |
  12. | react | class | 函数式 + hook |
  13. **函数式编程优点**:
  14. 1. 代码逻辑更加清晰,**可以脱离class this/bind 编程**(这是js语言的特性,与react无关)
  15. 1. 使用hook之后,**封装和复用都变得更加简单**,**结构清晰**
  16. 1. 之前要用高阶组件的方式,层级深了后,会比较混乱(最明显的是redux支持hook后,使用起来简单多了)
  17. 3. **组合式apihook)**,让逻辑变得**更加的集中**,**不会分散**,使大型项目会更好维护
  18. 1. **可以写多个 useState + useEffect 的组合**,**让逻辑更加集中**(vue也可以写多个 onMountedwatch
  19. 1. **之前的话,在大型复杂应用中:数据只能在state内,一个生命周期钩子内,会包含很多七零八落、互不相关的逻辑。例如**:
  20. ```jsx
  21. // 用class,类编程
  22. class FriendStatusWithCounter extends React.Component {
  23. constructor(props) {
  24. super(props);
  25. this.state = { count: 0, isOnline: null }; // 互不相关的数据,也只能写在state里面,
  26. this.handleStatusChange = this.handleStatusChange.bind(this);
  27. }
  28. componentDidMount() { // 2段互不相关的逻辑,写在里面
  29. document.title = `You clicked ${this.state.count} times`;
  30. ChatAPI.subscribeToFriendStatus(
  31. this.props.friend.id,
  32. this.handleStatusChange
  33. );
  34. }
  35. componentDidUpdate() {
  36. document.title = `You clicked ${this.state.count} times`;
  37. }
  38. componentWillUnmount() {
  39. ChatAPI.unsubscribeFromFriendStatus(
  40. this.props.friend.id,
  41. this.handleStatusChange
  42. );
  43. }
  44. handleStatusChange(status) {
  45. this.setState({
  46. isOnline: status.isOnline
  47. });
  48. }
  49. }
  50. // ----------------------------------------
  51. // 用hook 函数式编程
  52. function FriendStatusWithCounter(props) {
  53. const [count, setCount] = useState(0);
  54. useEffect(() => {
  55. document.title = `You clicked ${count} times`;
  56. });
  57. const [isOnline, setIsOnline] = useState(null);
  58. useEffect(() => {
  59. function handleStatusChange(status) {
  60. setIsOnline(status.isOnline);
  61. }
  62. ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  63. return () => {
  64. ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  65. };
  66. });
  67. }
  1. 弱化生命周期概念,一个useEffect 就可以替代3个生命周期。vue3也去掉了2个钩子
    1. 这方面react做的比vue更彻底。不过,虽然编码更清晰,但可能也会让新手不好理解useEffect

React vs Vue

相同点:

  1. 都是spa单页面,性能、生态、编码体验都很不错,都是基于虚拟dom + diff算法更新页面。vue也可以写jsx。用vue写jsx的话,写法上基本和react就很像了,就是一些api的用法不一样

不同点 (6个方面):

  1. vue会多做一层模板编译(vue-loader, VueLoaderPlugin),这样带来的好处:
    1. 可以支持3段式的写法,对新手比较友好 ```html

```

  1. 很容易做css模块化,解决样式冲突问题
  2. 可以支持指令,具名插槽,比如 v-model v-if v-show v-for、v-on
  3. 更容易做静态分析,做性能优化。比如:缓存静态节点 和 节点事件
    1. vue更偏向于自动挡,react 手动挡
  4. pureComponent,React.memo
    1. react有pureComponent,React.memo 这种做渲染优化,当state或props的值没改变时,即使触发了setState也不触发render。
    2. 这个在vue里面就是自动的,相当于默认就加好了
    3. 但是 react可以通过 shouldComponentUpdate 控制某些情况不render,vue做不到
  5. 对于使用 router 和 redux的store 时
    1. vue都是自动高阶函数注入的(mixin),每个组件都可以直接通过this去获取。使用起来非常简单
    2. react则需要自己手动的用高阶函数的方式注入store,props的方式往下传递,使用起来很麻烦不过,有hook之后,会简单很多
    3. 不过对于vue2来说,这是不可控的,无论你是否要用store或router,他们都被挂到了当前组件的实例上面。vue3支持手动控制
  6. setState触发render方面
    1. vue是响应式的,是自动的,直接改数据就能触发render。不用主动调用setState,也不用做对象的merge合并。
      • vue3用了Proxy会更彻底的监听,vue2的监听 缺陷还是有一些
    2. react需要主动调setState,并且存在同步/异步的情况。
      • 正常在react控制范围内,多次setState就是异步的 只会render一次(内部做了性能优化)但在react 控制范围之外,比如setTimeout,addEventListener的回调函数内,多次setState会render多次(有些损害性能)
    3. vue不会有这个问题,统一是异步的只render一次
    4. react多次setState 也不会拿不到上一次的值,需要传回调函数才能拿到上一次的值
    5. 状态管理方面
  7. 较为接近
  8. vuex使用起来要更简单一点,vuex用mutation替代了redux的reducer里面的switch,并通过store.commit传入对于mutation的名字 可以直接触发类似react的 dispatch。
  9. vue还多了一个事件监听和发射emit,多了一种子传父的方式
    1. 封装组件方面
  10. 普通组件props组件比较接近
  11. slot方面差别较大
    1. vue有具名插槽,react是render props
  12. react原生支持jsx,vue需要配置才能支持jsx
    1. 如果vue开发者不熟悉jsx的话,jsx的封装能力 个人觉得 要比vue本身的形式 要强
      • 因为,用jsx的话,逻辑可以按需 按函数的形式 拆成更多小快
      • vue的话,一个.vue文件内,一般是3段式,只会存在一个组件。需要别的组件要外引。react中一个.jsx文件内,可以存在N个组件
    2. vue如果写jsx的话,这方面就也差不多。但vue的开发者,写jsx的比较少
  13. 样式污染方面
    1. vue自带处理了css module的问题,react需要用create-react-app支持,或额外配置
    2. diff算法方面
  14. react是双指针,只支持前前遍历。比如 123 变成了 4123,那就扫不到,如果没设置key的话,会全部重新替换
  15. vue是4指针除了前前遍历,还有前后,后前,后后遍历
  16. 都支持为元素加key,在进一步提升性能。(key值最好稳定一点,否则损耗性能)
  17. 因为dom树的层级结构一般情况下,都不会有大改变,并且标签类型很少会改变。所以:
    1. 如果标签的类型改变了(比如div变成span),那会直接创建一个新的标签+里面的内容,不会在往下遍历。 同类型标签,才会进一步去查找差异点
    2. 都是 只支持兄弟元素间的位置变动,不支持移动到其他位置。移到其他位子会重新渲染整颗子树
    3. Fiber方面
      vue3为什么不使用 Time Slicing(Fiber)?
  18. 作者尢大大回答过,大致的意思是:vue很快,没必要做Fiber
    1. vue用模板渲染,更易于做静态分析,和一些渲染方面的优化。运行时的性能很高很快,延迟情况较少。
      (没有时间切片-> 没有fiber-> 更少的开销)本质上更简单,因此虚拟DOM操作更快
      通过分析模板进行了大量的AOT优化,减少了虚拟DOM操作的基本开销。Benchmark显示,对于一个典型的DOM代码块来说,动态与静态内容的比例大约是1:4,Vue3的原生执行速度甚至比Svelte更快,在CPU上花费的时间不到React的1/10。
      (pureComponent,vue是自动的)智能组件树级优化通过响应式跟踪,将插槽编译成函数(避免子元素重复渲染)和自动缓存内联句柄(避免内联函数重复渲染)。除非必要,否则子组件永远不需要重新渲染。这一切不需要开发人员进行任何手动优化。
      这意味着对于同一个更新,React应用可能造成多个组件重新渲染,但在Vue中大部分情况下只会导致一个组件重新渲染。
    2. 一般超过16ms的cpu任务,时间切片开始发挥作用。但是除非在进行动画,否则100ms内的掉帧用户一般无感知(并且动画可以用GPU硬件加速优化)
    3. 另外,如果是大量DOM更新操作,那么无论是否用了Fiber,都会有丢帧的感觉
    4. 并且使用Fiber架构本身会增加核心库体积和cpu计算

码字不易,点赞鼓励!!