React 跟 Vue 数据更新的区别

3,945 阅读3分钟

React 更新流程

此处介绍的 React 版本是 16.x。

想来大家应该知道,React 推崇数据 Immutable,当然这跟它自身有很大关系,它设计跟 Vue 完全不同,不是通过收集数据依赖去发现更新的,而是通过 re-render 去发现和更新自身。当然,React 推崇 Immutable 也是很有意义的,这篇文章 Immutable 详解及 React 中实践 #3 介绍了 Immutable 一些知识。

所以,React 要求我们使用 setStatehook 中 的 useState 的 setXXX(value) 去更新数据,进而触发更新。

React 的更新流程大概如下:

setState -> re-render(beginWork 递 & completeWork 归 )-> commit -> before mutation -> mutation -> layout

以上流程中, beginWorkcompleteWork 并没有先后顺序,请看下图(图片来源于卡老师的 React技术揭秘):

其中有很多知识点,如 Fiber, 生命周期的触发,数据更新等,这里就不详细说了。

Vue 更新流程

Vue 最令人称道的,应该是其响应式更新。配合模版食用,让人不禁发出:真香!

此处介绍的 Vue 的版本是 2.x 的。

从图中可以知道,Vue 通过首次渲染操作,触发了 Datagetter ,从而触发了依赖收集,为对应的数据创建 watcher,当数据发生更改时,也就是 setter 被触发了,那么,将会通知各个 watcher,在下一个 tick 时,会更新数据。更详细的数据绑定原理的知识,可以从这里从源码角度再看数据绑定.MarkDown 获得。

此处,需要注意的地方是,Vue 是通过渲染来触发数据的依赖收集的,也就是说,假如 Data 中有某些数据并没有在模版中使用的话,更新这些数据的时候,是不会触发更新的。

<template>
	<p>
    {{txtA}}
  </p>	
	<p>
    {{+new Date()}}
  </p>	
	<div @click="changeA">
   	changeA
  </div>
	<div @click="changeB">
   	changeB
  </div>
</template>

<script>
	export default {
    data() {
      return {
        txtA: 'hello',
        txtB: 'hi'
      }
    },
    methods: {
      changeA() {
        console.log('changeA~');
        this.txtA = 'world';
      },
      changeB() {
        console.log('changeB~');
        this.txtB = 'guy';
      }
    }
  }
</script>

如上代码,当 txtA 被赋新值后,页面的时间戳会发生变化,但 txtB 被赋新值,时间戳是不变化的,也就是并没有触发到更新

不过这正是理想中的啊,没有在模版上用到的变量,当它的值发生变化时,就不应该更新视图。

补充一下 Vue 的初始化流程和更新流程:

初始流程

// 初始化props、methods、data、computed与watch
initState(vm) 

template -> parse -> (AST) -> optimize -> generate -> (vNode) -> patch -> 映射到真实DOM

更新流程

watcher -> vNode -> patch -> 映射到真实DOM

React vs Vue 区别

从上面 ReactVue 的更新流程的介绍,应该可以得出他们对数据更新的区别之处:

  1. 获取数据更新的手段和更新的粒度不一样
    • Vue 通过依赖收集,当数据更新时, Vue 明确地知道是哪些数据更新了,每个组件都有自己的渲染 watcher ,掌管当前组件的视图更新,所以可以精确地更新对应的组件,所以更新的粒度是组件级别的。
    • React 会递归地把所有的子组件 re-render 一下,不管是不是更新的数据,此时,都是新的。然后通过 diff 算法 来决定更新哪部分的视图。所以,React 的更新粒度是一个整体。
  2. 对更新数据是否需要渲染页面的处理不一样
    • 只有依赖收集的数据发生更新,Vue 才会去重新渲染页面
    • 只要数据有更新(setStateuseState 等手段触发更新),都会去重新渲染页面(可以使用shouldComponentUpdate/ PureComponent 改善)

参考

深入响应式原理

从源码角度再看数据绑定.MarkDown

从template到DOM(Vue.js源码角度看内部运行机制).MarkDown

Immutable 详解及 React 中实践 #3

beginWork 和 completeWork

面试官:Vue 和 React 对于组件的更新粒度有什么区别?