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

900 阅读8分钟

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. 缓存 模板上元素绑定的事件
      <div id="app">
        <button @click="handleClick">戳我</button>
        <button @click="() => {
            console.log(111)
          }">戳我</button>
      </div>
      
      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)
          })
          }, "戳我")
        ]))
      }
      
    2. 增加对静态节点的标记,相当于缓存静态节点
      <div id="app">
          <h1>我是静态节点</h1>
      
          <div>{{name}}</div>
          <div :class="{red:isRed}">摸鱼符</div>
          <button @click="handleClick">戳我</button>
          <input type="text" v-model="name">
      </div>
      
      // 打包后
      import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
      
      export function render(_ctx, _cache) {
        return (_openBlock(), _createBlock("div", { id: "app" }, [
          _createVNode("h1", null, "我是静态节点"),
          _createVNode("div", null, _toDisplayString(_ctx.name), 1 /* TEXT */),
          _createVNode("div", {
            class: {red:_ctx.isRed}
          }, "动态节点", 2 /* CLASS */),
          _createVNode("button", { onClick: _ctx.handleClick }, "戳我", 8 /* PROPS */, ["onClick"])
        ]))
      }
      
        // 动态节点注释表  
        TEXT = 1,// 表示具有动态textContent的元素
        CLASS = 1 << 1,  // 表示有动态Class的元素
        STYLE = 1 << 2,  // 表示动态样式(静态如style="color: red",也会提升至动态)
        PROPS = 1 << 3,  // 表示具有非类/样式动态道具的元素。
        FULL_PROPS = 1 << 4,  // 表示带有动态键的道具的元素,与上面三种相斥
        HYDRATE_EVENTS = 1 << 5,  // 表示带有事件监听器的元素
        STABLE_FRAGMENT = 1 << 6,   // 表示其子顺序不变的片段(没懂)。 
        KEYED_FRAGMENT = 1 << 7, // 表示带有键控或部分键控子元素的片段。
        UNKEYED_FRAGMENT = 1 << 8, // 表示带有无key绑定的片段
        NEED_PATCH = 1 << 9,   // 表示只需要非属性补丁的元素,例如ref或hooks
        DYNAMIC_SLOTS = 1 << 10,  // 表示具有动态插槽的元素
      
  3. 类编程 到 函数式编程 (vue2 到 vue3)

    1. 组合式api:大型应用中,逻辑可以组合在一起,会更清晰好维护
    2. 某些方面变得更加手动而不是自动。
    • 在vue2中,每个组件都会被自动注入route和store,vue3变得可控
    • 在组合式api内,可以像react一样,写多个hook组合,比如
      // 如果是vue2的话,数据只能放在data里,生命周期钩子只能有一个,多段无关逻辑 都耦合在钩子里
      
      // 以下是vue3,组合式
      const aa = ref(1)
      onMounted(() => {
        console.log(aa.value)
      })
      watch(...)
      
      const cc = ref('')
      computed(...)
      onMounted(() => {
        console.log('处理cc的逻辑')
      })
      
  4. 更好typescript支持

  5. 响应式核心api 从 Object.definedProperty -> Proxy更加彻底的监听

  6. vite

    1. 基本原理是浏览器支持esm,不过需要高版本浏览器,chorme都要61以上,支持动态import要chorme63

    2. 热更新和重新启动都非常快,并且热更新的速度不会随项目变大而变慢

      1. 第一次构建还是需要时间,之后就很快。第一次需要依赖预构建 用的esbuild(速度很快)

类编程 vs 函数式编程

类编程函数式编程
vuevue2vue3(setup内)
reactclass函数式 + hook

函数式编程优点

  1. 代码逻辑更加清晰,可以脱离class的 this/bind 编程(这是js语言的特性,与react无关)

  2. 使用hook之后,封装和复用都变得更加简单结构清晰

    1. 之前要用高阶组件的方式,层级深了后,会比较混乱(最明显的是redux支持hook后,使用起来简单多了)
  3. 组合式api(hook),让逻辑变得更加的集中不会分散,使大型项目会更好维护

    1. 可以写多个 useState + useEffect 的组合让逻辑更加集中(vue也可以写多个 onMounted,watch)
    2. 之前的话,在大型复杂应用中:数据只能在state内,一个生命周期钩子内,会包含很多七零八落、互不相关的逻辑。例如
      // 用class,类编程
      class FriendStatusWithCounter extends React.Component {
        constructor(props) {
          super(props);
          this.state = { count: 0, isOnline: null }; // 互不相关的数据,也只能写在state里面,
          this.handleStatusChange = this.handleStatusChange.bind(this);
        }
      
        componentDidMount() { // 2段互不相关的逻辑,写在里面
          document.title = `You clicked ${this.state.count} times`;
          ChatAPI.subscribeToFriendStatus(
            this.props.friend.id,
            this.handleStatusChange
          );
        }
      
        componentDidUpdate() {
          document.title = `You clicked ${this.state.count} times`;
        }
      
        componentWillUnmount() {
          ChatAPI.unsubscribeFromFriendStatus(
            this.props.friend.id,
            this.handleStatusChange
          );
        }
      
        handleStatusChange(status) {
          this.setState({
            isOnline: status.isOnline
          });
        }
      }
      
      // ----------------------------------------
      
      // 用hook 函数式编程
      function FriendStatusWithCounter(props) {
        const [count, setCount] = useState(0);
        useEffect(() => {    
          document.title = `You clicked ${count} times`;
        });
      
        const [isOnline, setIsOnline] = useState(null);
        useEffect(() => {    
          function handleStatusChange(status) {
            setIsOnline(status.isOnline);
          }
      
          ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
          return () => {
            ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
          };
        });
      }
      
  4. 弱化生命周期概念,一个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段式的写法,对新手比较友好
      <template>
      </template>
      
      <script>
      </script>
      
      <style scoped> // css模块化,解决样式冲突问题
      </style>
      
    2. 很容易做css模块化,解决样式冲突问题
    3. 可以支持指令,具名插槽,比如 v-model v-if v-show v-for、v-on
    4. 更容易做静态分析,做性能优化。比如:缓存静态节点 和 节点事件
  2. vue更偏向于自动挡,react 手动挡

    1. pureComponent,React.memo

      1. react有pureComponent,React.memo 这种做渲染优化,当state或props的值没改变时,即使触发了setState也不触发render。
      2. 这个在vue里面就是自动的,相当于默认就加好了
      3. 但是 react可以通过 shouldComponentUpdate 控制某些情况不render,vue做不到
    2. 对于使用 router 和 redux的store 时

      1. vue都是自动高阶函数注入的(mixin),每个组件都可以直接通过this去获取。使用起来非常简单
      2. react则需要自己手动的用高阶函数的方式注入store,props的方式往下传递,使用起来很麻烦不过,有hook之后,会简单很多
      3. 不过对于vue2来说,这是不可控的,无论你是否要用store或router,他们都被挂到了当前组件的实例上面。vue3支持手动控制
    3. 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 也不会拿不到上一次的值,需要传回调函数才能拿到上一次的值
  3. 状态管理方面

    1. 较为接近
    2. vuex使用起来要更简单一点,vuex用mutation替代了redux的reducer里面的switch,并通过store.commit传入对于mutation的名字 可以直接触发类似react的 dispatch。
    3. vue还多了一个事件监听和发射emit,多了一种子传父的方式
  4. 封装组件方面

    1. 普通组件props组件比较接近

    2. slot方面差别较大

      1. vue有具名插槽,react是render props
    3. react原生支持jsx,vue需要配置才能支持jsx

      1. 如果vue开发者不熟悉jsx的话,jsx的封装能力 个人觉得 要比vue本身的形式 要强
        • 因为,用jsx的话,逻辑可以按需 按函数的形式 拆成更多小快
        • vue的话,一个.vue文件内,一般是3段式,只会存在一个组件。需要别的组件要外引。react中一个.jsx文件内,可以存在N个组件
      2. vue如果写jsx的话,这方面就也差不多。但vue的开发者,写jsx的比较少
    4. 样式污染方面

      1. vue自带处理了css module的问题,react需要用create-react-app支持,或额外配置
  5. diff算法方面

    1. react是双指针,只支持前前遍历。比如 123 变成了 4123,那就扫不到,如果没设置key的话,会全部重新替换

    2. vue是4指针除了前前遍历,还有前后,后前,后后遍历

    3. 都支持为元素加key,在进一步提升性能。(key值最好稳定一点,否则损耗性能)

    4. 因为dom树的层级结构一般情况下,都不会有大改变,并且标签类型很少会改变。所以:

      1. 如果标签的类型改变了(比如div变成span),那会直接创建一个新的标签+里面的内容,不会在往下遍历。 同类型标签,才会进一步去查找差异点
      2. 都是 只支持兄弟元素间的位置变动,不支持移动到其他位置。移到其他位子会重新渲染整颗子树
  6. Fiber方面

    vue3为什么不使用 Time Slicing(Fiber)?

    1. 作者尢大大回答过,大致的意思是: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计算


码字不易,点赞鼓励!!