facebook immutable.js 意义何在,使用场景?

有人用facebook的immutablejs吗?能不能解释一下为什么使用,意义何在?使用场景?
关注者
1,169
被浏览
148,616

19 个回答

写了篇文章介绍这个事情,欢迎大家去看,

搞定immutable.js

什么是Immutable Data

Immutable Data是指一旦被创造后,就不可以被改变的数据。

通过使用Immutable Data,可以让我们更容易的去处理缓存、回退、数据变化检测等问题,简化我们的开发。

js中的Immutable Data

在javascript中我们可以通过deep clone来模拟Immutable Data,就是每次对数据进行操作,新对数据进行deep clone出一个新数据。

deep clone

/**
 * learning-immutable - clone-deep.js
 * Created by mds on 15/6/6.
 */

'use strict';  
var cloneDeep = require('lodash.clonedeep');

var data = {  
    id: 'data',
    author: {
        name: 'mdemo',
        github: 'https://github.com/demohi'
    }
};

var data1 = cloneDeep(data);

console.log('equal:', data1===data); //false

data1.id = 'data1';  
data1.author.name = 'demohi';

console.log(data.id);// data  
console.log(data1.id);// data1

console.log(data.author.name);//mdemo  
console.log(data1.author.name);//demohi  

当然你或许意识到了,这样非常的慢。如下图,确实很慢

主角immutable.js登场

immutable.js是由facebook开源的一个项目,主要是为了解决javascript Immutable Data的问题,通过参考hash maps triesvector tries提供了一种更有效的方式。

简单的来讲,immutable.js通过structural sharing来解决的性能问题。我们先看一段视频,看看immutable.js是如何做的

当我们发生一个set操作的时候,immutable.js会只clone它的父级别以上的部分,其他保持不变,这样大家可以共享同样的部分,可以大大提高性能。

为什么你要在React.js中使用Immutable Data

熟悉React.js的都应该知道,React.js是一个UI = f(states)的框架,为了解决更新的问题,React.js使用了virtual dom,virtual dom通过diff修改dom,来实现高效的dom更新。

听起来很完美吧,但是有一个问题。当state更新时,如果数据没变,你也会去做virtual dom的diff,这就产生了浪费。这种情况其实很常见,可以参考flummox这篇文章

当然你可能会说,你可以使用PureRenderMixin来解决呀,PureRenderMixin是个好东西,我们可以用它来解决一部分的上述问题,但是如果你留心的话,你可以在文档中看到下面这段提示。

This only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only mix into components which have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.

PureRenderMixin只是简单的浅比较,不使用于多层比较。那怎么办??自己去做复杂比较的话,性能又会非常差。

方案就是使用immutable.js可以解决这个问题。因为每一次state更新只要有数据改变,那么PureRenderMixin可以立刻判断出数据改变,可以大大提升性能。这部分还可以参考官方文档Immutability Helpers

总结就是:使用PureRenderMixin + immutable.js

参考

React.js Conf 2015 - Immutable Data and React

Immutability Helpers

PureRenderMixin

immutable-js

最近在移动端使用 React,在复杂的页面里发现 vdom re-render 有性能优化的空间,于是了解到了 immutable.js。所以也来回答一下这个问题。

@张克军

所说:

  • 它是一个完全独立的库,无论基于什么框架都可以用它。意义在于它弥补了Javascript 没有不可变数据结构的问题。
  • 在React开发中,频繁操作 state 对象或是 store,配合 immutableJS 快、安全

克军说的第一点:函数式编程中的不可变数据结构问题,可参考

@徐飞

的文章《

2015前端组件化框架之路

》中 Immutable Data 章节。

我就第二点来展开说说 immutableJS 的使用场景:在 React 中使用 immutableJS (

Immutable as React state · facebook/immutable-js Wiki · GitHub

)。

从问题说起:

熟悉 React 组件生命周期的话都知道:调用

setState

方法总是会触发

render

方法从而进行 vdom re-render 相关逻辑,哪怕实际上你没有更改到 Component.state 。

```javascript

this.state = {count: 0}

this.setState({count: 0});// 组件 state 并未被改变,但仍会触发 render 方法

```

为了避免这种性能上的浪费,React 提供了一个

shouldComponentUpdate

来控制触发 vdom re-render 逻辑的条件。于是

PureRenderMixin

作为一种优化技巧被使用。

这样就完美了?并不是。去趴一趴 PureRenderMixin 的源码(

react/shallowEqual.js at master · facebook/react · GitHub

)就会发现它仅仅是浅比较对象,深层次的数据结构根本不管用。这里有一个示例:

JS Bin1

,点击 SetToSameCount ,会发现 render times 没有变化,再点 SetToSameSchool ,render times 增加了。

这时候 immutableJS 就派得上用场了:

```javascript

var map1 = Immutable.fromJS({a:1, b:1, c:{b:{c:{d:{e:7}}}}});

var map2 = Immutable.fromJS({a:1, b:1, c:{b:{c:{d:{e:7}}}}});

Immutable.is(map1, map2); // true

```

当然上述功能通过 deep-diff 也可以做到(e.g.

flitbit/diff · GitHub

),性能差别上我暂时没有去进行测试。

但是,如果仅仅是为了一个比较而引入 Immutable 的话,就太大材小用了。Immutable 的功能远不止如此。

例如,前面的

JS Bin1

示例中的场景:(在 Hight school name 的 input 内中输入触发 handleChangeSchool 就会发现 middle 属性被删除了)

这样调用 setState 会将 middle 属性给覆盖掉(setState 内部是浅 merge)。在实际项目中,我们将会频繁地操作 state 或 store ,这时候配合 Immutable 就快且安全多了:

看一个上面的示例怎样用 Immutable 重写一遍:

JS Bin2

快:

  • 便捷的API:```d.updateIn(['user','school', 'high'], ()=>v)``` 更多参考:Immutable.js
  • 更好的性能:facebook/immutable-js · GitHub (They are highly efficient on modern JavaScript VMs by using structural sharing via hash maps tries and vector tries as popularized by Clojure and Scala, minimizing the need to copy or cache data.) (暂时未给出性能测试)

安全:是指使用上的安全,所有删改操作都是增量的。如

JS Bin2

示例中更新 school high name 所示,并没有影响到 middle 。

这就是 Immutable 在我们项目中的使用场景了。