immutable 和 React 的那些事儿

immutable 的中文意思叫做不可改变的,那不可改变的数据结构有什么优势呢?它与 React 会擦出什么样的火花呢?它底层又是如何实现的呢?我们接下来一起来看。

为什么要 immutable

我们在书写代码的时候可能会做出这样的操作:

function sortMyArray(arr) {
  arr.sort((a, b) => a - b);
  // ...
}
1
2
3
4

我们虽然能够得到正确的结果,但是非常遗憾的是这个数组被我们改变了,他经过我们的函数被污染了,再使用到其他地方就可能得到意想不到的结果。

所以在平常的开发过程中,我们要有 immutable 的意识。

那么为什么我们说 immutable 适合 react 呢?我们接着看。

immutable 和 react

众所周知,React 更新方式是由 stateprops 的更新引起的,当某个组件发生更新的时候,React 会根据最新的状态构建一颗新的 virtual DOM 树,然后使用 diff 算法进行对比,如果不同则会进行渲染。

React 中 shouldComponentUpdate 默认返回 true,所以当更改某一个叶子节点的状态时,整个树形都会重新渲染,即使是那些状态没有更新的节点,这在某种程度上耗费了性能。

基于这些问题 React 又提出了 PureComponent,它实现了对数据进行了浅比较,虽然这解决了一部分问题,但是还是没有根本性的解决这个问题。

比如说,数据是这样变动的:

[{name: 'pre', data: {}}]
// =====> 只改变了 name 属性
[{name: 'after', data: {}}]
1
2
3

这样的数据改变并没有引起组件的更新,这显然是不对的,这是因为这两个对象的引用是相同的,同时数组长度也相同。

那么,我们要如何解决这个问题呢?

  1. 深拷贝:改变了引用地址,自然就会更新了,但是太消耗内存。
  2. JSON.stringify: 这也是深拷贝的一种黑魔法了,有局限性,会断掉原型链,同时有些东西并不能使用这种方式拷贝,比如函数。

接下来我们要说的就是 immutable.js 了,虽然实现 immutable 的库比较多,但这里就挑一个来说。

它的特点就是 持久化数据结构结构共享,保证每一个对象都是不可变的,任何添加、删除、修改等操作都会返回一个新的对象,并且通过结构共享提高性能。

比如说,我们在一个对象中新增加一个节点,那么就把这个对象到根节点的路径上的节点全部重新生成,而其余的结构不变,这样整个对象的引用改变了,但是却只修改一部分数据,大大提高了性能。

immutable 如何实现

immutable.js 参考了 Vector Trie 这种数据结构,使用了位分区的方式,同时加上哈希表来实现的。

具体的分析可以看这篇文章,我这儿就不多解释了。

Last Updated: 1/13/2019, 10:35:05 PM