Immutable 详解

By admin in 4858美高梅 on 2019年4月8日

Shared mutable state is the root of all
evil(共享的可变状态是万恶之源)

— Pete Hunt

作者:camsong
链接:https://zhuanlan.zhihu.com/p/20295971
来源:知乎

MMUTABLE 详解

Shared mutable state is the root of all
evil(共享的可变状态是万恶之源)

— Pete Hunt

有人说 Immutable 能够给 React 应用带来数十倍的升官,也有人说 Immutable
的引进是最近 JavaScript 中硬汉的表达,因为同期 React
太火,它的光线被遮盖了。这一个起码注解 Immutable
是很有价值的,上面大家来1探终归。

JavaScript
中的对象一般是可变的(Mutable),因为使用了引用赋值,新的靶子简单的引用了原来对象,改变新的对象将影响到原来对象。如
foo={a: 1}; bar=foo; bar.a=2 你会发觉此时 foo.a 也被改成了
2。就算那样做能够节本省部存款和储蓄器,但当使用复杂后,这就招致了要命大的隐患,Mutable
带来的亮点变得因小失大。为了化解那个题材,一般的做法是应用
shallowCopy(浅拷贝)或 deepCopy(深拷贝)来幸免被涂改,但如此做造成了
CPU 和内部存款和储蓄器的荒废。

Immutable 能够很好地消除那几个题材。

有人说 Immutable 能够给 React 应用带来数10倍的晋升,也有人说 Immutable
的引进是近日 JavaScript 中大侠的阐发,因为同期 React
太火,它的光柱被掩盖了。这个起码注解 Immutable
是很有价值的,上面大家来1探毕竟。

有人说 Immutable 能够给 React 应用带来数10倍的升级换代,也有人说 Immutable
的引进是近些年 JavaScript 中国和英国豪的表明,因为同期 React
太火,它的光柱被覆盖了。那个起码表明 Immutable
是很有价值的,上面大家来一探毕竟。

Shared mutable state is the root of all
evil(共享的可变状态是万恶之源)
— Pete Hunt

什么是 IMMUTABLE DATA

Immutable Data 正是只要创制,就无法再被更改的数目。对 Immutable
对象的其余修改或加上删减操作都会回来3个新的 Immutable 对象。Immutable
完结的原理是 Persistent Data
Structure(持久化数据结构),也便是运用旧数据创建新数据时,要保管旧数据同时可用且不变。同时为了幸免deepCopy 把装有节点都复制贰回带来的习性损耗,Immutable 使用了 Structural
Sharing(结构共享),即只要指标树中一个节点产生变化,只修改那几个节点和受它影响的父节点,其余节点则进行共享。请看上面动画:

4858美高梅 1

现阶段盛行的 Immutable 库有三个:

JavaScript
中的对象一般是可变的(Mutable),因为运用了引用赋值,新的目的简单的引用了本来对象,改变新的靶子将震慑到原来对象。如
foo={a: 1}; bar=foo; bar.a=2您会发觉此时 foo.a 也被改成了
二。纵然这么做能够节约内存,但当使用复杂后,那就造成了分外大的隐患,Mutable
带来的优点变得寸进尺退。为了消除这些标题,1般的做法是运用
shallowCopy(浅拷贝)或 deepCopy(深拷贝)来制止被涂改,但这么做造成了
CPU 和内存的荒废。
Immutable 能够很好地化解那么些标题。

JavaScript
中的对象1般是可变的(Mutable),因为运用了引用赋值,新的对象不难的引用了原来对象,改变新的指标将震慑到原有对象。如 foo={a: 1}; bar=foo; bar.a=2 你会发现此时 foo.a 也被改成了 2。即便这么做能够节约内部存款和储蓄器,但当使用复杂后,那就造成了至极大的隐患,Mutable
带来的帮助和益处变得以珠弹雀。为了消除那么些标题,一般的做法是应用
shallowCopy(浅拷贝)或 deepCopy(深拷贝)来幸免被涂改,但这么做造成了
CPU 和内部存款和储蓄器的荒废。

有人说 Immutable 能够给 React 应用带来数10倍的提高,也有人说 Immutable
的引进是近年 JavaScript 中铁汉的申明,因为同期 React
太火,它的光辉被掩盖了。这一个起码评释 Immutable
是很有价值的,上面大家来一探终究。

immutable.js

推文(Tweet)(Facebook) 工程师 Lee 拜伦 花费 三 年时间制作,与 React
同期出现,但并未有被暗中认可放到 React 工具集里(React 提供了简化的
Helper)。它在那之中贯彻了一套完整的 Persistent Data
Structure,还有很多易用的数据类型。像
CollectionListMapSetRecordSeq。有特别健全的mapfiltergroupByreduce``find函数式操作方法。同时
API 也尽量与 Object 或 Array 类似。

中间有 3 种最首要的数据结构说多美滋(Dumex)下:(Java 程序员应该最熟习了)

  • Map:键值对聚集,对应于 Object,ES陆 也有越发的 Map 对象
  • List:有序可另行的列表,对应于 Array
  • Set:冬季且不可重复的列表

Immutable 详解。什么是 Immutable Data

Immutable 能够很好地消除那些题材。

JavaScript
中的对象一般是可变的(Mutable),因为使用了引用赋值,新的指标简单的引用了原始对象,改变新的靶子将影响到原来对象。如
foo={a: 1}; bar=foo; bar.a=2 你会意识此时 foo.a 也被改成了
2。即使如此做能够节省里部存款和储蓄器,但当使用复杂后,那就招致了丰裕大的隐患,Mutable
带来的亮点变得寸进尺退。为了缓解那几个难题,一般的做法是选用shallowCopy(浅拷贝)或 deepCopy(深拷贝)来制止被改动,但诸如此类做造成了
CPU 和内存的浪费。
Immutable 能够很好地消除那些难题。

seamless-immutable

与 Immutable.js 高校派的品格差异,seamless-immutable 并从未落实全体的
Persistent Data Structure,而是选取 Object.defineProperty(由此只可以在
IE九 及以上使用)增添了 JavaScript 的 Array 和 Object 对象来落到实处,只支持Array 和 Object 三种数据类型,API 基于与 Array 和 Object
操持不变。代码库不大,压缩后下载唯有 2K。而 Immutable.js 压缩后下载有
1陆K。

下面上代码来感受一下两者的分化:

// 原来的写法
let foo = {a: {b: 1}};
let bar = foo;
bar.a.b = 2;
console.log(foo.a.b);  // 打印 2
console.log(foo === bar);  //  打印 true

// 使用 immutable.js 后
import Immutable from 'immutable';
foo = Immutable.fromJS({a: {b: 1}});
bar = foo.setIn(['a', 'b'], 2);   // 使用 setIn 赋值
console.log(foo.getIn(['a', 'b']));  // 使用 getIn 取值,打印 1
console.log(foo === bar);  //  打印 false

// 使用  seamless-immutable.js 后
import SImmutable from 'seamless-immutable';
foo = SImmutable({a: {b: 1}})
bar = foo.merge({a: { b: 2}})   // 使用 merge 赋值
console.log(foo.a.b);  // 像原生 Object 一样取值,打印 1
console.log(foo === bar);  //  打印 false

Immutable Data 就是1旦成立,就不能够再被更改的多少。对 Immutable
对象的任何改动或丰硕删减操作都会重返3个新的 Immutable 对象。Immutable
实现的法则是 Persistent Data
Structure(持久化数据结构),也正是使用旧数据创制新数据时,要力保旧数据同时可用且不变。同时为了制止deepCopy 把具有节点都复制1遍带来的质量损耗,Immutable 使用了 Structural
Sharing(结构共享),即要是指标树中1个节点爆发变化,只修改那个节点和受它影响的父节点,其余节点则展开共享。请看上边动画:

什么是 Immutable Data

Immutable Data 就是1旦创造,就无法再被更改的数额。对 Immutable
对象的别的改动或丰盛删减操作都会重返一个新的 Immutable 对象。Immutable
达成的规律是 Persistent Data
Structure(持久化数据结构),也正是选用旧数据创造新数据时,要力保旧数据同时可用且不变。同时为了制止deepCopy 把全体节点都复制3次带来的品质损耗,Immutable 使用了 Structural
Sharing(结构共享),即假如指标树中几个节点发生变化,只修改这些节点和受它影响的父节点,其余节点则开始展览共享。请看上面动画:

4858美高梅 2

最近风行的 Immutable 库有七个:

什么是 Immutable Data

IMMUTABLE 优点

擦,费了好大劲做了个 Gif 动画,竟然被威逼转成了静态图,请移步

观看
时下风靡的 Immutable 库有七个:

immutable.js

推文(Tweet) 工程师 Lee Byron 开支 3 年时间制作,与 React
同期出现,但未有被暗中认可放到 React 工具集里(React 提供了简化的
Helper)。它当中贯彻了壹套完整的 Persistent Data
Structure,还有为数不少易用的数据类型。像 CollectionListMapSetRecordSeq。有那个健全的mapfiltergroupByreduce``find函数式操作方法。同时
API 也尽可能与 Object 或 Array 类似。

里面有 3 种最重大的数据结构说可瑞康(Karicare)(Nutrilon)下:(Java 程序员应该最熟稔了)

  • Map:键值对聚集,对应于 Object,ES陆 也有特意的 Map 对象
  • List:有序可重复的列表,对应于 Array
  • Set:冬日且不可重复的列表

Immutable Data 便是要是创建,就不能够再被更改的数目。对 Immutable
对象的其余改动或抬高删减操作都会回去三个新的 Immutable 对象。Immutable
达成的规律是 Persistent Data
Structure(持久化数据结构),约等于运用旧数据成立新数据时,要有限支撑旧数据同时可用且不变。同时为了制止deepCopy 把装有节点都复制三遍带来的属性损耗,Immutable 使用了 Structural
Sharing(结构共享),即假设目的树中3个节点发生变化,只修改这几个节点和受它影响的父节点,别的节点则开始展览共享。请看上边动画:

一. Immutable 降低了 Mutable 带来的复杂度

可变(Mutable)数据耦合了 Time 和 Value 的定义,造成了数量很难被回溯。

诸如下边1段代码:

function touchAndLog(touchFn) {
  let data = { key: 'value' };
  touchFn(data);
  console.log(data.key); // 猜猜会打印什么?
}

在不查看 touchFn 的代码的气象下,因为不明确它对 data
做了怎样,你是不大概清楚会打字与印刷什么(那不是废话吗)。但万一 data
Immutable 的吗,你能够很肯定的敞亮打字与印刷的是 value

1.immutable.js

seamless-immutable

与 Immutable.js 高校派的风格区别,seamless-immutable 并不曾兑现完全的
Persistent Data Structure,而是利用 Object.defineProperty(由此只能在
IE九 及以上使用)扩展了 JavaScript 的 Array 和 Object 对象来促成,只匡助Array 和 Object 三种数据类型,API 基于与 Array 和 Object
操持不变。代码库相当小,压缩后下载只有 2K。而 Immutable.js 压缩后下载有
1陆K。

下边上代码来感受一下两者的差异:

// 原来的写法
let foo = {a: {b: 1}};
let bar = foo;
bar.a.b = 2;
console.log(foo.a.b);  // 打印 2
console.log(foo === bar);  //  打印 true

// 使用 immutable.js 后
import Immutable from 'immutable';
foo = Immutable.fromJS({a: {b: 1}});
bar = foo.setIn(['a', 'b'], 2);   // 使用 setIn 赋值
console.log(foo.getIn(['a', 'b']));  // 使用 getIn 取值,打印 1
console.log(foo === bar);  //  打印 false

// 使用  seamless-immutable.js 后
import SImmutable from 'seamless-immutable';
foo = SImmutable({a: {b: 1}})
bar = foo.merge({a: { b: 2}})   // 使用 merge 赋值
console.log(foo.a.b);  // 像原生 Object 一样取值,打印 1
console.log(foo === bar);  //  打印 false

擦,费了好大劲做了个 Gif 动画,竟然被要挟转成了静态图,请移步
http://img.alicdn.com/tps/i2/TB1zzi\_KXXXXXctXFXXbrb8OVXX-613-575.gif
观看
当下风靡的 Immutable 库有四个:

二. 节约内存

Immutable.js 使用了 Structure Sharing
会尽量复用内部存款和储蓄器,甚至从前使用的指标也得以重新被复用。未有被引述的靶子会被垃圾回收。

import { Map} from 'immutable';
let a = Map({
  select: 'users',
  filter: Map({ name: 'Cam' })
})
let b = a.set('select', 'people');

a === b; // false
a.get('filter') === b.get('filter'); // true

上边 a 和 b 共享了未曾转变的 filter 节点。

Facebook 工程师 Lee Byron 开销 3 年时间制作,与 React
同期出现,但未有被暗中同意放到 React 工具集里(React 提供了简化的
Helper)。它当中贯彻了1套完整的 Persistent Data
Structure,还有好多易用的数据类型。像
Collection、List、Map、Set、Record、Seq。有那么些完美的map、filter、groupBy、reduce“find函数式操作方法。同时
API 也尽恐怕与 Object 或 Array 类似。

Immutable 优点

  1. immutable.js

三. Undo/Redo,Copy/Paste,甚至时间旅行这一个效应做起来小菜一碟

因为每一回数据都以区别的,只要把这个数量放到3个数组里储存起来,想回退到哪儿就拿出相应数据即可,很简单开发出废除重做那种效益。

后边作者会提供 Flux 做 Undo 的示范。

里面有 3 种最重大的数据结构说雀巢(Nestle)下:(Java 程序员应该最熟习了)

1. Immutable 跌落了 Mutable 带来的复杂度

可变(Mutable)数据耦合了 Time 和 Value 的定义,造成了多少很难被回溯。

譬如下边壹段代码:

function touchAndLog(touchFn) {
  let data = { key: 'value' };
  touchFn(data);
  console.log(data.key); // 猜猜会打印什么?
}

在不查看 touchFn 的代码的动静下,因为不明确它对 data 做了如何,你是不容许知道会打字与印刷什么(那不是废话吗)。但只要 data 是
Immutable 的吗,你能够很自然的敞亮打印的是 value

Facebook 工程师 Lee Byron 花费 三 年时间营造,与 React
同期出现,但尚无被暗中同意放到 React 工具集里(React 提供了简化的
Helper)。它里面贯彻了一套完整的 Persistent Data
Structure,还有不少易用的数据类型。像
CollectionListMapSetRecordSeq。有十一分完美的mapfiltergroupByreduce``find函数式操作方法。同时
API 也尽或然与 Object 或 Array 类似。

四. 油但是生安全

历史观的出现非常难做,因为要拍卖各个数码不等同难题,由此『聪明人』发明了各类锁来缓解。但采纳了
Immutable 之后,数据天生是不可变的,并发锁就不要求了。

可是未来并没什么卵用,因为 JavaScript
依旧单线程运营的啊。但前途大概会参与,提前化解今后的标题不也挺好呢?

Map:键值对聚集,对应于 Object,ES六 也有专门的 Map 对象
List:有序可再度的列表,对应于 Array
Set:冬季且不可重复的列表

二. 节省外存

Immutable.js 使用了 Structure Sharing
会尽量复用内部存款和储蓄器,甚至在此以前使用的对象也得以再一次被复用。没有被引用的靶子会被垃圾回收。

import { Map} from 'immutable';
let a = Map({
  select: 'users',
  filter: Map({ name: 'Cam' })
})
let b = a.set('select', 'people');

a === b; // false
a.get('filter') === b.get('filter'); // true

地方 a 和 b 共享了未有变化的 filter 节点。

内部有 三 种最重大的数据结构说澳优(Ausnutria Hyproca)下:(Java 程序员应该最通晓了)

五. 搂抱函数式编制程序

Immutable
本身便是函数式编制程序中的概念,纯函数式编程比面向对象更适用于前端开发。因为一旦输入1致,输出必然壹致,那样开发的零部件更易于调节和测试和组建。

像 ClojureScript,Elm 等函数式编制程序语言中的数据类型天生都以 Immutable
的,那也是干吗 ClojureScript 基于 React 的框架 — Om 质量比 React
还要好的缘故。

2.seamless-immutable

三. Undo/Redo,Copy/Paste,甚至时间旅行这几个意义做起来小菜壹碟

因为老是数据都以不雷同的,只要把那些多少放到2个数组里储存起来,想回退到何地就拿出相应数据即可,很不难开发出打消重做那种效果。

末端作者会提供 Flux 做 Undo 的演示。

Map:键值对聚集,对应于 Object,ES6 也有特意的 Map 对象
List:有序可重新的列表,对应于 Array
Set:严节且不可重复的列表

IMMUTABLE 缺点

与 Immutable.js 高校派的风骨分歧,seamless-immutable 并未有实现全体的
Persistent Data Structure,而是选择 Object.defineProperty(由此只可以在
IE玖 及以上使用)扩大了 JavaScript 的 Array 和 Object 对象来落实,只支持Array 和 Object 二种数据类型,API 基于与 Array 和 Object
操持不变。代码库非常的小,压缩后下载唯有 2K。而 Immutable.js 压缩后下载有
1陆K。

四. 冒出安全

古板的出现相当难做,因为要拍卖各类数据不一致难题,由此『聪明人』发明了种种锁来缓解。但使用了
Immutable 之后,数据天生是不可变的,并发锁就不供给了。

唯独现在并没什么卵用,因为 JavaScript
照旧单线程运营的哟。但前途大概会进入,提前化解以往的题材不也挺行吗?

  1. seamless-immutable

1. 须求学习新的 API

No Comments

下边上代码来感受一下两者的不等:

五. 搂抱函数式编制程序

Immutable
本身就是函数式编程中的概念,纯函数式编程比面向对象更适用于前端开发。因为只要输入1致,输出必然一致,那样开发的机件更易于调节和测试和组装。

像 ClojureScript,Elm 等函数式编制程序语言中的数据类型天生都以 Immutable
的,那也是干什么 ClojureScript 基于 React 的框架 — Om 质量比 React
还要好的原由。

与 Immutable.js 高校派的品格分歧,seamless-immutable 并从未落到实处一体化的
Persistent Data Structure,而是选取 Object.defineProperty(由此只万幸IE玖 及以上使用)扩大了 JavaScript 的 Array 和 Object 对象来贯彻,只帮忙Array 和 Object 二种数据类型,API 基于与 Array 和 Object
操持不变。代码库一点都不大,压缩后下载只有 2K。而 Immutable.js 压缩后下载有
1六K。

二. 日增了资源文件大小

No Comments

// 原来的写法
let foo = {a: {b: 1}};
let bar = foo;
bar.a.b = 2;
console.log(foo.a.b); // 打印 2
console.log(foo === bar); // 打印 true
// 使用 immutable.js 后
import Immutable from ‘immutable';
foo = Immutable.fromJS({a: {b: 1}});
bar = foo.setIn([‘a', ‘b'], 2);  // 使用 setIn 赋值
console.log(foo.getIn([‘a', ‘b'])); // 使用 getIn 取值,打印 1
console.log(foo === bar); // 打印 false
// 使用 seamless-immutable.js 后
import SImmutable from ‘seamless-immutable';
foo = SImmutable({a: {b: 1}})
bar = foo.merge({a: { b: 2}})  // 使用 merge 赋值
console.log(foo.a.b); // 像原生 Object 一样取值,打印 1
console.log(foo === bar); // 打印 false

Immutable 缺点

下边上代码来感受一下两者的差别:

三. 便于与原生对象混淆

这一点是我们使用 Immutable.js
进度中遇到最大的标题。写代码要做思虑上的生成。

就算如此 Immutable.js 尽量尝试把 API
设计的原生对象类似,有的时候依然很难差距到底是 Immutable
对象依旧原生对象,简单混淆视听操作。

Immutable 中的 Map 和 List 虽对应原生 Object 和
Array,但操作十一分例外,比如你要用 map.get('key')而不是
map.keyarray.get(0) 而不是 array[0]。其它 Immutable
每一次修改都会回去新目的,也很简单忘记赋值。

当使用外部库的时候,壹般要求动用原生对象,也很不难忘记转换。

上面给出1些措施来幸免类似题材发出:

  1. 行使 Flow 或 TypeScript 那类有静态类型检查的工具
  2. 预订变量命名规则:如全体 Immutable 类型对象以 $$ 开头。
  3. 使用 Immutable.fromJS 而不是 Immutable.MapImmutable.List
    来创立对象,那样能够制止 Immutable 和原生对象间的混用。

Immutable 优点

一. 急需上学新的 API

No Comments

// 原来的写法
let foo = {a: {b: 1}};
let bar = foo;
bar.a.b = 2;
console.log(foo.a.b);  // 打印 2
console.log(foo === bar);  //  打印 true

// 使用 immutable.js 后
import Immutable from ‘immutable’;
foo = Immutable.fromJS({a: {b: 1}});
bar = foo.setIn([‘a’, ‘b’], 2);   // 使用 setIn 赋值
console.log(foo.getIn([‘a’, ‘b’]));  // 使用 getIn 取值,打印 1
console.log(foo === bar);  //  打印 false

// 使用  seamless-immutable.js 后
import SImmutable from ‘seamless-immutable’;
foo = SImmutable({a: {b: 1}})
bar = foo.merge({a: { b: 2}})   // 使用 merge 赋值
console.log(foo.a.b);  // 像原生 Object 一样取值,打印 1

console.log(foo === bar);  //  打印 false

更多认识

一 . Immutable 下滑了 Mutable 带来的复杂度

2. 充实了能源文件大小

No Comments

Immutable 优点

Immutable.is

多少个 immutable 对象能够运用 ===
来比较,那样是一贯比较内部存款和储蓄器地址,质量最棒。但尽管七个对象的值是1致的,也会回来
false

let map1 = Immutable.Map({a:1, b:1, c:1});
let map2 = Immutable.Map({a:1, b:1, c:1});
map1 === map2;             // false

为了直接相比对象的值,immutable.js 提供了 Immutable.is
来做『值相比』,结果如下:

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

Immutable.is 相比的是八个目的的 hashCodevalueOf(对于
JavaScript 对象)。由于 immutable 内部使用了 Trie
数据结构来囤积,只要三个指标的 hashCode
相等,值正是一模1样的。那样的算法幸免了纵深遍历比较,品质尤其好。

末尾会使用 Immutable.is 来减弱 React 重复渲染,提升质量。

另外,还有
mori、cortex
等,因为接近就不再介绍。

可变(Mutable)数据耦合了 Time 和 Value 的概念,造成了多少很难被回溯。

叁. 简单与原生对象混淆

那点是大家应用 Immutable.js
进度中相见最大的标题。写代码要做思虑上的变动。

虽说 Immutable.js 尽量尝试把 API
设计的原生对象类似,有的时候依旧很难差异到底是 Immutable
对象仍旧原生对象,简单混淆视听操作。

Immutable 中的 Map 和 List 虽对应原生 Object 和
Array,但操作11分例外,比如你要用 map.get('key')而不是 map.keyarray.get(0) 而不是 array[0]。此外Immutable 每一趟修改都会回到新目的,也很不难忘记赋值。

当使用外部库的时候,1般须求利用原生对象,也很不难忘记转换。

下边给出一些艺术来制止类似问题时有产生:

  1. 应用 Flow 或 TypeScript 那类有静态类型检查的工具
  2. 预订变量命名规则:如全体 Immutable 类型对象以 $$ 开头。
  3. 使用 Immutable.fromJS 而不是 Immutable.Map 或 Immutable.List 来成立对象,这样可避防止Immutable 和原生对象间的混用。

1 . Immutable 骤降了 Mutable 带来的复杂度

与 Object.freeze、const 区别

Object.freeze 和 ES陆 中新加盟的 const
都能够达到规定的标准预防对象被篡改的功力,但它们是 shallowCopy
的。对象层级一深就要卓绝处理了。

比如上边1段代码:

更加多认识

可变(Mutable)数据耦合了 Time 和 Value 的定义,造成了数码很难被回溯。

Cursor 的概念

本条 Cursor 和数据库中的游标是一心不相同的定义。

是因为 Immutable 数据貌似嵌套相当深,为了便利访问深层数据,Cursor
提供了足以平昔访问这几个深层数据的引用。

import Immutable from 'immutable';
import Cursor from 'immutable/contrib/cursor';

let data = Immutable.fromJS({ a: { b: { c: 1 } } });
// 让 cursor 指向 { c: 1 }
let cursor = Cursor.from(data, ['a', 'b'], newData => {
  // 当 cursor 或其子 cursor 执行 update 时调用
  console.log(newData);
});

cursor.get('c'); // 1
cursor = cursor.update('c', x => x + 1);
cursor.get('c'); // 2
function touchAndLog(touchFn) {
  let data = { key: ‘value' };
  touchFn(data);
  console.log(data.key); // 猜猜会打印什么?
}

Immutable.is

三个 immutable
对象能够运用 === 来相比较,那样是从来相比较内部存款和储蓄器地址,品质最佳。但固然四个指标的值是一致的,也会回来 false

let map1 = Immutable.Map({a:1, b:1, c:1});
let map2 = Immutable.Map({a:1, b:1, c:1});
map1 === map2;             // false

为了直接相比对象的值,immutable.js
提供了 Immutable.is 来做『值相比较』,结果如下:

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

Immutable.is 相比较的是五个目的的 hashCode 或 valueOf(对于
JavaScript 对象)。由于 immutable 内部选择了 Trie
数据结构来存款和储蓄,只要三个指标的 hashCode 相等,值正是壹模一样的。这样的算法制止了纵深遍历比较,质量非凡好。

后边会选拔 Immutable.is 来减弱 React 重复渲染,升高质量。

另外,还有 mori、cortex 等,因为接近就不再介绍。

例如上边一段代码:

实践

在不查看 touchFn 的代码的情状下,因为不鲜明它对 data
做了什么样,你是不或者知道会打印什么(那不是废话吗)。但借使 data 是
Immutable 的吧,你能够很肯定的知道打字与印刷的是 value。

与 Object.freeze、const 区别

Object.freeze 和 ES六中新参与的 const 都能够高达预防对象被歪曲的效能,但它们是 shallowCopy
的。对象层级壹深就要极度处理了。

function touchAndLog(touchFn) {
    let data = { key: ‘value’ };
    touchFn(data);
    console.log(data.key); // 猜猜会打印什么?
}

与 React 搭配使用,Pure Render

熟谙 React 的都精晓,React
做质量优化时有3个幸免重新渲染的大招,便是选用
shouldComponentUpdate(),但它暗中认可重回 true,即始终会履行 render()
方法,然后做 Virtual DOM 相比较,并得出是不是须要坚实际 DOM
更新,那里往往会推动很多无必要的渲染并变成性能瓶颈。

自然大家也能够在 shouldComponentUpdate() 中使用使用 deepCopy 和
deepCompare 来制止无供给的 render(),但 deepCopy 和 deepCompare
一般都以可怜耗性能的。

Immutable 则提供了简洁高效的论断数据是不是变动的措施,只需 ===is
比较就能领略是或不是必要履行 render(),而那一个操作大致 0
成本,所以能够小幅增强质量。修改后的 shouldComponentUpdate 是这样的:

注意:React 中规定 stateprops
只好是3个经常对象,所以相比较时要相比对象的 key,谢谢
@chenmnkken
指正。

import { is } from 'immutable';

shouldComponentUpdate: (nextProps = {}, nextState = {}) => {
  const thisProps = this.props || {}, thisState = this.state || {};

  if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
      Object.keys(thisState).length !== Object.keys(nextState).length) {
    return true;
  }

  for (const key in nextProps) {
    if (!is(thisProps[key], nextProps[key])) {
      return true;
    }
  }

  for (const key in nextState) {
    if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
      return true;
    }
  }
  return false;
}

动用 Immutable 后,如下图,当灰色节点的 state
变化后,不会再渲染树中的全体节点,而是只渲染图羊毛牡蛎白的部分:

4858美高梅 3

您也足以凭借 React.addons.PureRenderMixin 或支持 class 语法的
[pure-render-decorator](felixgirault/pure-render-decorator · GitHub)
来实现。

二 . 节省外部存款和储蓄器

Cursor 的概念

本条 Cursor 和数据库中的游标是截然两样的概念。

出于 Immutable 数据貌似嵌套非凡深,为了有利于访问深层数据,Cursor
提供了能够直接待上访问那个深层数据的引用。

import Immutable from 'immutable';
import Cursor from 'immutable/contrib/cursor';

let data = Immutable.fromJS({ a: { b: { c: 1 } } });
// 让 cursor 指向 { c: 1 }
let cursor = Cursor.from(data, ['a', 'b'], newData => {
  // 当 cursor 或其子 cursor 执行 update 时调用
  console.log(newData);
});

cursor.get('c'); // 1
cursor = cursor.update('c', x => x + 1);
cursor.get('c'); // 2

在不查看 touchFn 的代码的场所下,因为不分明它对 data
做了哪些,你是不容许知道会打字与印刷什么(那不是废话吗)。但假若 data
Immutable 的吗,你能够很肯定的敞亮打字与印刷的是 value

setState 的一个技术

React 建议把 this.state 当作 Immutable 的,由此修改前要求做3个deepCopy,显得麻烦:

import '_' from 'lodash';

const Component = React.createClass({
  getInitialState() {
    return {
      data: { times: 0 }
    }
  },
  handleAdd() {
    let data = _.cloneDeep(this.state.data);
    data.times = data.times + 1;
    this.setState({ data: data });
    // 如果上面不做 cloneDeep,下面打印的结果会是已经加 1 后的值。
    console.log(this.state.data.times);
  }
}

使用 Immutable 后:

  getInitialState() {
    return {
      data: Map({ times: 0 })
    }
  },
  handleAdd() {
    this.setState({ data: this.state.data.update('times', v => v + 1) });
    // 这时的 times 并不会改变
    console.log(this.state.data.get('times'));
  }

上面的 handleAdd 可以简写成:

  handleAdd() {
    this.setState(({data}) => ({
      data: data.update('times', v => v + 1) })
    });
  }

Immutable.js 使用了 Structure Sharing
会尽量复用内部存款和储蓄器。未有被引述的靶子会被垃圾回收。

实践

2 . 节本省存

与 Flux 搭配使用

鉴于 Flux 并从未范围 Store 中数据的品类,使用 Immutable 格外不难。

前天是达成3个类似带有添加和裁撤功能的 Store:

import { Map, OrderedMap } from 'immutable';
let todos = OrderedMap();
let history = [];  // 普通数组,存放每次操作后产生的数据

let TodoStore = createStore({
  getAll() { return todos; }
});

Dispatcher.register(action => {
  if (action.actionType === 'create') {
    let id = createGUID();
    history.push(todos);  // 记录当前操作前的数据,便于撤销
    todos = todos.set(id, Map({
      id: id,
      complete: false,
      text: action.text.trim()
    }));
    TodoStore.emitChange();
  } else if (action.actionType === 'undo') {
    // 这里是撤销功能实现,
    // 只需从 history 数组中取前一次 todos 即可
    if (history.length > 0) {
      todos = history.pop();
    }
    TodoStore.emitChange();
  }
});
import { Map} from ‘immutable';
 let a = Map({
 select: ‘users',
 filter: Map({ name: ‘Cam' })
})
let b = a.set(‘select', ‘people');
a === b; // false
a.get(‘filter') === b.get(‘filter'); // true

与 React 搭配使用,Pure Render

熟稔 React 的都明白,React
做品质优化时有3个幸免重复渲染的大招,就是运用 shouldComponentUpdate(),但它默许重回 true,即始终会执行 render() 方法,然后做
Virtual DOM 相比,并搜查捕获是还是不是供给做真实 DOM
更新,那里往往会带来众多无须要的渲染并变成质量瓶颈。

本来大家也得以在 shouldComponentUpdate() 中使用使用 deepCopy 和
deepCompare 来制止无须要的 render(),但 deepCopy 和 deepCompare
1般都以不行耗质量的。

Immutable
则提供了精简高效的论断数据是不是变动的措施,只需 === 和 is 相比就能通晓是还是不是须求履行 render(),而以此操作差不多0
开支,所以可以非常的大增长品质。修改后的 shouldComponentUpdate 是那样的:

注意:React
中规定 state 和 props 只好是3个平常对象,所以相比时要相比对象的 key,谢谢 @chenmnkken 指正。

import { is } from 'immutable';

shouldComponentUpdate: (nextProps = {}, nextState = {}) => {
  const thisProps = this.props || {}, thisState = this.state || {};

  if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
      Object.keys(thisState).length !== Object.keys(nextState).length) {
    return true;
  }

  for (const key in nextProps) {
    if (!is(thisProps[key], nextProps[key])) {
      return true;
    }
  }

  for (const key in nextState) {
    if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
      return true;
    }
  }
  return false;
}

采纳 Immutable 后,如下图,当米色节点的 state
变化后,不会再渲染树中的全部节点,而是只渲染图豆珍珠白的1部分:

4858美高梅 4

您也得以依靠 React.addons.PureRenderMixin 或支持 class 语法的
[pure-render-decorator](felixgirault/pure-render-decorator · GitHub)
来实现。

Immutable.js 使用了 Structure Sharing
会尽量复用内部存款和储蓄器。没有被引述的指标会被垃圾回收。

与 Redux 搭配使用

Redux
是眼下盛行的 Flux 衍生库。它简化了 Flux 中七个 Store 的概念,唯有3个Store,数据操作通过 Reducer
中贯彻;同时它提供更简洁和明晰的单向数据流(View -> Action ->
Middleware ->
Reducer),也更易于开发同构应用。近日一度在大家项目中常见利用。

是因为 Redux 中置放的 combineReducers 和 reducer 中的 initialState
都为原生的 Object 对象,所以不能够和 Immutable 原生搭配使用。

碰巧的是,Redux 并不排外使用 Immutable,能够团结重写 combineReducers
或使用
redux-immutablejs
来提供支持。

地点大家关系 Cursor 能够方便寻找和 update 层级比较深的数额,但因为 Redux
中早已有了 select 来做检索,Action 来更新数据,由此 Cursor
在此处就从未用武之地了。

上边 a 和 b 共享了从未生成的 `filter` 节点。

setState 的三个技能

React 建议把 this.state 当作 Immutable 的,由此修改前需求做3个deepCopy,显得麻烦:

import '_' from 'lodash';

const Component = React.createClass({
  getInitialState() {
    return {
      data: { times: 0 }
    }
  },
  handleAdd() {
    let data = _.cloneDeep(this.state.data);
    data.times = data.times + 1;
    this.setState({ data: data });
    // 如果上面不做 cloneDeep,下面打印的结果会是已经加 1 后的值。
    console.log(this.state.data.times);
  }
}

使用 Immutable 后:

  getInitialState() {
    return {
      data: Map({ times: 0 })
    }
  },
  handleAdd() {
    this.setState({ data: this.state.data.update('times', v => v + 1) });
    // 这时的 times 并不会改变
    console.log(this.state.data.get('times'));
  }

上面的 handleAdd 能够简写成:

  handleAdd() {
    this.setState(({data}) => ({
      data: data.update('times', v => v + 1) })
    });
  }
import { Map} from ‘immutable’;
  let a = Map({
  select: ‘users’,
  filter: Map({ name: ‘Cam’ })
})
let b = a.set(‘select’, ‘people’);

a === b; // false

a.get(‘filter’) === b.get(‘filter’); // true
上面 a 和 b 共享了没有变化的 `filter` 节点。

总结

Immutable
能够给使用带来巨大的性质提高,可是还是不是选取还要看项目情状。由于侵入性较强,新品类引进比较易于,老品种搬迁须求评估迁移。对于有些提需要外部使用的国有组件,最棒不要把
Immutable 对象直接暴露在对外接口中。

假设 JS 原生 Immutable 类型会不会太美,被誉为 React API 终结者的
塞BathTyne 马克båge
有三个这么的提案,能不能够通过今后还不明确。然则能够毫无疑问的是
Immutable 会被越多的类型利用。

三 .
Undo/Redo,Copy/Paste,甚至时间旅行这么些效用做起来小菜一碟

与 Flux 搭配使用

由于 Flux 并从未限定 Store 中数据的品类,使用 Immutable 格外简单。

今日是实现3个好录像带有添加和废除效用的 Store:

import { Map, OrderedMap } from 'immutable';
let todos = OrderedMap();
let history = [];  // 普通数组,存放每次操作后产生的数据

let TodoStore = createStore({
  getAll() { return todos; }
});

Dispatcher.register(action => {
  if (action.actionType === 'create') {
    let id = createGUID();
    history.push(todos);  // 记录当前操作前的数据,便于撤销
    todos = todos.set(id, Map({
      id: id,
      complete: false,
      text: action.text.trim()
    }));
    TodoStore.emitChange();
  } else if (action.actionType === 'undo') {
    // 这里是撤销功能实现,
    // 只需从 history 数组中取前一次 todos 即可
    if (history.length > 0) {
      todos = history.pop();
    }
    TodoStore.emitChange();
  }
});

三 . Undo/Redo,Copy/Paste,甚至时间旅行这么些成效做起来小菜壹碟

因为每趟数据都是不等同的,只要把那个数据放到3个数组里储存起来,想回退到何地就拿出相应数据即可,很不难开发出撤消重做那种效率。

与 Redux 搭配使用

Redux 是日前盛行的 Flux
衍生库。它简化了 Flux 中多个 Store 的概念,唯有1个 Store,数据操作通过
Reducer 中贯彻;同时它提供更简短和明晰的单向数据流(View -> Action
-> Middleware ->
Reducer),也更易于开发同构应用。近来早就在大家项目中常见利用。

出于 Redux 中放到的 combineReducers 和 reducer
中的 initialState 都为原生的 Object 对象,所以不可能和 Immutable
原生搭配使用。

有幸的是,Redux 并不排外使用
Immutable,能够友善重写 combineReducers 或使用 redux-immutablejs 来提供支撑。

地点大家提到 Cursor 能够一本万利寻找和 update 层级比较深的数码,但因为 Redux
中曾经有了 select 来做检索,Action 来更新数据,由此 Cursor
在此地就从不用武之地了。

因为老是数据都以不一致的,只要把这几个数据放到三个数组里储存起来,想回退到何地就拿出相应数据即可,很不难开发出撤废重做那种效益。

后面小编会提供 Flux 做 Undo 的以身作则。

总结

Immutable
能够给采纳带来巨大的属性升高,可是还是不是采用还要看档次情形。由于侵入性较强,新品类引进相比便于,老项目搬迁须要评估迁移。对于部分提要求外部使用的国有组件,最佳不用把
Immutable 对象直接揭露在对外接口中。

借使 JS 原生 Immutable 类型会不会太美,被叫做 React API 终结者的
Sebastian 马克båge
有一个这么的提案,能或不可能通过今后还不分明。可是能够毫无疑问的是
Immutable 会被进一步多的项目应用。

末尾小编会提供 Flux 做 Undo 的演示。

4 . 并发安全

肆 . 并发安全

守旧的出现非常难做,因为要处理各个数据不均等难题,由此『聪明人』发明了种种锁来缓解。但使用了
Immutable 之后,数据天生是不可变的,并发锁就不须要了。

古板的面世非常难做,因为要处理各个数据不均等难题,由此『聪明人』发明了种种锁来化解。但使用了
Immutable 之后,数据天生是不可变的,并发锁就不必要了。

但是未来并没什么卵用,因为 JavaScript
仍然单线程运维的哎。但前途说不定会加盟,提前化解今后的难点不也挺行吗?

不过将来并不妨卵用,因为 JavaScript
依然单线程运行的呦。但前景说不定会加入,提前消除今后的题材不也挺好吧?

拥抱函数式编制程序

  1. 拥抱函数式编制程序

Immutable
自个儿正是函数式编制程序中的概念,纯函数式编制程序比面向对象更适用于前端开发。因为一旦输入一致,输出必然一致,那样开发的零部件更易于调节和测试和组建。

Immutable
本人正是函数式编制程序中的概念,纯函数式编制程序比面向对象更适用于前端开发。因为1旦输入一致,输出必然壹致,那样开发的零部件更便于调节和测试和组建。

像 ClojureScript,Elm 等函数式编制程序语言中的数据类型天生都以 Immutable
的,这也是怎么 ClojureScript 基于 React 的框架 — Om 品质比 React
还要好的原由。

像 ClojureScript,Elm 等函数式编程语言中的数据类型天生都是 Immutable
的,那也是怎么 ClojureScript 基于 React 的框架 — Om 质量比 React
还要好的来头。

使用 Immutable 的缺点

使用 Immutable 的缺点

急需上学新的 API

  1. 内需上学新的 API
    No Comments

  2. 充实了能源文件大小
    No Comments

  3. 不难与原生对象混淆

No Comments

那一点是我们运用 Immutable.js
进程中境遇最大的难题。写代码要做思想上的变型。

充实了财富文件大小

就算 Immutable.js 尽量尝试把 API
设计的原生对象类似,有的时候依旧很难差异到底是 Immutable
对象照旧原生对象,简单模糊操作。

No Comments

Immutable 中的 Map 和 List 虽对应原生 Object 和
Array,但操作尤其例外,比如您要用 map.get(‘key’) 而不是
map.keyarray.get(0) 而不是 array[0]。别的 Immutable
每一趟修改都会回去新对象,也很简单忘记赋值。

简单与原生对象混淆

当使用外部库的时候,1般要求接纳原生对象,也很简单忘记转换。

4858美高梅,那点是我们使用 Immutable.js
进度中境遇最大的题材。写代码要做思想上的变型。

上边给出1些艺术来幸免类似题材发生:

就算如此 Immutable.js 尽量尝试把 API
设计的原生对象类似,有的时候依然很难不一致到底是 Immutable
对象如故原生对象,简单混淆操作。

运用 Flow 或 TypeScript 那类有静态类型检查的工具
约定变量命名规则:如全体 Immutable 类型对象以 $$ 开头。
使用 Immutable.fromJS 而不是 Immutable.MapImmutable.List
来创立对象,那样能够制止 Immutable 和原生对象间的混用。
越来越多认识

Immutable 中的 Map 和 List 虽对应原生 Object 和
Array,但操作越发例外,比如您要用 map.get(‘key’) 而不是
map.key,array.get(0) 而不是 array[0]。别的 Immutable
每一回修改都会回去新对象,也很不难忘记赋值。

1 . Immutable.is
多少个 immutable 对象足以应用 ===
来比较,这样是直接相比较内部存款和储蓄器地址,品质最佳。但哪怕多少个目的的值是同一的,也会回去
false

当使用外部库的时候,一般供给使用原生对象,也很不难忘记转换。

let map1 = Immutable.Map({a:1, b:1, c:1});
let map2 = Immutable.Map({a:1, b:1, c:1});
map1 === map2;             // false

上边给出一些措施来防止类似题材发出:

为了直接比较对象的值,immutable.js 提供了 Immutable.is
来做『值比较』,结果如下:

行使 Flow 或 TypeScript 那类有静态类型检查的工具

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

预定变量命名规则:如享有 Immutable 类型对象以 $$ 开头。

Immutable.is 相比较的是三个对象的 hashCodevalueOf(对于
JavaScript 对象)。由于 immutable 内部采纳了 Trie
数据结构来储存,只要八个指标的 hashCode
相等,值就是平等的。那样的算法制止了纵深遍历相比较,质量格外好。

选取 Immutable.fromJS 而不是 Immutable.Map 或 Immutable.List
来创立对象,那样可避防止 Immutable 和原生对象间的混用。

末端会利用 Immutable.is 来裁减 React 重复渲染,升高质量。

越来越多认识

除此以外,还有 mori、cortex 等,因为类似就不再介绍。

1 . Immutable.is

2 . 与 Object.freeze、const 区别

三个 immutable 对象足以行使 ===
来相比较,这样是一直相比较内部存款和储蓄器地址,质量最棒。但不怕八个目的的值是一样的,也会回到
false:

Object.freeze 和 ES陆 中新进入的 const
都能够达到预防对象被篡改的功效,但它们是 shallowCopy
的。对象层级1深就要特殊处理了。

let map1 = Immutable.Map({a:1, b:1, c:1});
let map2 = Immutable.Map({a:1, b:1, c:1});
map1 === map2;       // false

3 . Cursor 的概念

为了直接比较对象的值,immutable.js 提供了 Immutable.is
来做『值比较』,结果如下:

其1 Cursor 和数据库中的游标是一心差别的定义。

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

鉴于 Immutable 数据1般嵌套格外深,为了便于访问深层数据,Cursor
提供了足以一贯访问那么些深层数据的引用。

Immutable.is 比较的是四个对象的 hashCode 或 valueOf(对于 JavaScript
对象)。由于 immutable 内部选拔了 Trie 数据结构来储存,只要多少个对象的
hashCode 相等,值就是平等的。这样的算法防止了纵深遍历比较,质量13分好。

import Immutable from ‘immutable’;
import Cursor from ‘immutable/contrib/cursor’;

let data = Immutable.fromJS({ a: { b: { c: 1 } } });
// 让 cursor 指向 { c: 1 }
let cursor = Cursor.from(data, [‘a’, ‘b’], newData => {
// 当 cursor 或其子 cursor 执行 update 时调用
console.log(newData);
});

cursor.get(‘c’); // 1
cursor = cursor.update(‘c’, x => x + 1);
cursor.get(‘c’); // 2

末尾会利用 Immutable.is 来压缩 React 重复渲染,进步品质。

实践

除此以外,还有 mori、cortex 等,因为类似就不再介绍。

  1. 与 React 搭配使用,Pure Render

2 . 与 Object.freeze、const 区别

领会 React 的都掌握,React
做质量优化时有四个幸免重新渲染的大招,正是运用
shouldComponentUpdate(),但它默许重返 true,即始终会履行 render()
方法,然后做 Virtual DOM 相比,并搜查捕获是不是供给坚实际 DOM
更新,那里往往会拉动很多无供给的渲染并成为品质瓶颈。

Object.freeze 和 ES陆 中新加盟的 const
都足以达到预防对象被曲解的功力,但它们是 shallowCopy
的。对象层级壹深就要特殊处理了。

理所当然我们也能够在 shouldComponentUpdate() 中使用应用 deepCopy 和
deepCompare 来防止无须要的 render(),但 deepCopy 和 deepCompare
1般都以充足耗品质的。

3 . Cursor 的概念

Immutable 则提供了简短高效的判断数据是还是不是变动的法门,只需 ===is
比较就能知道是还是不是须要执行 render(),而那个操作大约 0
费用,所以能够大幅升高品质。修改后的 shouldComponentUpdate 是这么的:

本条 Cursor 和数据库中的游标是完全差别的定义。

import { is } from ‘immutable’;

  shouldComponentUpdate: (nextProps = {}, nextState = {}) => {
    const thisProps = this.props || {}, thisState = this.state || {};

    if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
      Object.keys(thisState).length !== Object.keys(nextState).length) {
        return true;
    }

    for (const key in nextProps) {
      if (thisProps[key] !== nextProps[key] || !is(thisProps[key],           nextProps[key])) {
      return true;
    }
  }

    for (const key in nextState) {
      if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
        return true;
      }
    }
    return false;
 }

是因为 Immutable 数据一般嵌套相当深,为了便利访问深层数据,Cursor
提供了足以一贯访问那一个深层数据的引用。

应用 Immutable 后,如下图,当中黄节点的 state
变化后,不会再渲染树中的全部节点,而是只渲染图褐色色的片段:

import Immutable from ‘immutable';
import Cursor from ‘immutable/contrib/cursor';
let data = Immutable.fromJS({ a: { b: { c: 1 } } });
// 让 cursor 指向 { c: 1 }
let cursor = Cursor.from(data, [‘a', ‘b'], newData => {
// 当 cursor 或其子 cursor 执行 update 时调用
console.log(newData);
});
cursor.get(‘c'); // 1
cursor = cursor.update(‘c', x => x + 1);
cursor.get(‘c'); // 2

4858美高梅 5

实践

005a24678dc39c202dbf3d1df96da13e_b.jpg

与 React 搭配使用,Pure Render

您也得以依靠 React.addons.PureRenderMixin 或支持 class
语法的pure-render-decorator 来实现。

深谙 React 的都掌握,React
做品质优化时有二个制止重新渲染的大招,正是利用
shouldComponentUpdate(),但它暗中认可再次来到 true,即始终会实施 render()
方法,然后做 Virtual DOM 比较,并搜查缉获是或不是必要加强际 DOM
更新,这里往往会带来很多无需求的渲染并变成品质瓶颈。

setState 的3个技能

理所当然大家也得以在shouldComponentUpdate()中利用使用 deepCopy 和
deepCompare 来幸免无须要的 render(),但 deepCopy 和 deepCompare
一般皆以老大耗性能的。

React 建议把 this.state 当作 Immutable 的,因此修改前供给做叁个deepCopy,显得麻烦:

Immutable 则提供了简洁高效的论断数据是不是变动的章程,只需 === 和 is
相比较就能精晓是否须要履行 render(),而以此操作差不多 0
成本,所以能够大幅增强质量。修改后的 shouldComponentUpdate是如此的:

import ‘_’ from ‘lodash’;

const Component = React.createClass({
getInitialState() {
return {
data: { times: 0 }
}
},
handleAdd() {
let data = _.cloneDeep(this.state.data);
data.times = data.times + 1;
this.setState({ data: data });
// 如果上面不做 cloneDeep,下面打印的结果会是已经加 1 后的值。
console.log(this.state.data.times);
}
}
import { is } from ‘immutable';
 shouldComponentUpdate: (nextProps = {}, nextState = {}) => {
  const thisProps = this.props || {}, thisState = this.state || {};
  if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
   Object.keys(thisState).length !== Object.keys(nextState).length) {
    return true;
  }
  for (const key in nextProps) {
   if (thisProps[key] !== nextProps[key] || !is(thisProps[key],      nextProps[key])) {
   return true;
  }
 }
  for (const key in nextState) {
   if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
    return true;
   }
  }
  return false;
 }

使用 Immutable 后:

行使 Immutable 后,如下图,当铜锈绿节点的 state
变化后,不会再渲染树中的全部节点,而是只渲染图水晶浅绿的壹些:

getInitialState() {
  return {
    data: Map({ times: 0 })
  }
},
handleAdd() {
  this.setState({ data: this.state.data.update(‘times’, v => v + 1) });
  // 这时的 times 并不会改变
  console.log(this.state.data.get(‘times’));
}

上面的 `handleAdd` 可以简写成:

handleAdd() {
  this.setState(({data}) => ({
  data: data.update(‘times’, v => v + 1) })
});
}

4858美高梅 6

贰 . 与 Flux 搭配使用

您也能够依靠 React.addons.PureRenderMixin或支持 class
语法的pure-render-decorator来实现。

出于 Flux 并从未范围 Store 中数据的类型,使用 Immutable 卓殊简单。
前几日是完结四个好录像带有添加和撤销作用的 Store:

setState 的3个技术

import { Map, OrderedMap } from ‘immutable’;
let todos = OrderedMap();
let history = [];  // 普通数组,存放每次操作后产生的数据

let TodoStore = createStore({
  getAll() { return todos; }
});

Dispatcher.register(action => {
  if (action.actionType === ‘create’) {
  let id = createGUID();
  history.push(todos);  // 记录当前操作前的数据,便于撤销
  todos = todos.set(id, Map({
    id: id,
    complete: false,
    text: action.text.trim()
  }));
TodoStore.emitChange();
} else if (action.actionType === ‘undo’) {
// 这里是撤销功能实现,
// 只需从 history 数组中取前一次 todos 即可
  if (history.length > 0) {
    todos = history.pop();
  }
  TodoStore.emitChange();
}
});

React 提出把 this.state 当作 Immutable 的,由此修改前必要做3个deepCopy,显得麻烦:

3 . 与 Redux 搭配使用

import ‘_' from ‘lodash';
const Component = React.createClass({
getInitialState() {
return {
data: { times: 0 }
}
},
handleAdd() {
let data = _.cloneDeep(this.state.data);
data.times = data.times + 1;
this.setState({ data: data });
// 如果上面不做 cloneDeep,下面打印的结果会是已经加 1 后的值。
console.log(this.state.data.times);
}
}

Redux 是当前风靡的 Flux 衍生库。它简化了 Flux 中多个 Store
的定义,只有1个 Store,数据操作通过 Reducer
中落到实处;同时它提供更简洁和明晰的单向数据流(View -> Action ->
Middleware ->
Reducer),也更便于开发同构应用。近年来早就在我们项目中广泛使用。

使用 Immutable 后:

是因为 Redux 中放置的 combineReducers 和 reducer 中的 initialState
都为原生的 Object 对象,所以不能够和 Immutable 原生搭配使用。

getInitialState() {
 return {
  data: Map({ times: 0 })
 }
},
handleAdd() {
 this.setState({ data: this.state.data.update(‘times', v => v + 1) });
 // 这时的 times 并不会改变
 console.log(this.state.data.get(‘times'));
}

有幸的是,Redux 并不排外使用 Immutable,能够友善重写 combineReducers
或选拔 redux-immutablejs 来提供支持。

上面的 `handleAdd` 能够简写成:

地方大家提到 Cursor 能够一本万利寻找和 update 层级相比深的多寡,但因为 Redux
中早就有了 select 来做检索,Action 来更新数据,因而 Cursor
在此处就从不用武之地了。

handleAdd() {
 this.setState(({data}) => ({
 data: data.update(‘times', v => v + 1) })
});
}

总结

二 . 与 Flux 搭配使用

Immutable
能够给使用带来巨大的特性升高,然而否利用还要看档次情况。由于侵入性较强,新品类引进比较易于,老品种搬迁须要评估迁移。对于有些提须要外部使用的公家组件,最棒不用把
Immutable 对象直接暴光在对外接口中。

由于 Flux 并未限定 Store 中多少的花色,使用 Immutable 非凡不难。

假诺 JS 原生 Immutable 类型会不会太美,被称作 React API 终结者的
塞BathTyne 马克båge
有二个那样的提案,能或不可能通过以后还不分明。然则可以毫无疑问的是 Immutable
会被进一步多的项目利用。

今昔是贯彻2个近似带有添加和注销成效的 Store:

import { Map, OrderedMap } from ‘immutable';
let todos = OrderedMap();
let history = []; // 普通数组,存放每次操作后产生的数据
let TodoStore = createStore({
 getAll() { return todos; }
});
Dispatcher.register(action => {
 if (action.actionType === ‘create') {
 let id = createGUID();
 history.push(todos); // 记录当前操作前的数据,便于撤销
 todos = todos.set(id, Map({
  id: id,
  complete: false,
  text: action.text.trim()
 }));
TodoStore.emitChange();
} else if (action.actionType === ‘undo') {
// 这里是撤销功能实现,
// 只需从 history 数组中取前一次 todos 即可
 if (history.length > 0) {
  todos = history.pop();
 }
 TodoStore.emitChange();
}
});

三 . 与 Redux 搭配使用

Redux 是如今风靡的 Flux 衍生库。它简化了 Flux 中四个 Store
的定义,唯有3个 Store,数据操作通过 Reducer
中完毕;同时它提供更简明和清楚的单向数据流(View -> Action ->
Middleware ->
Reducer),也更便于开发同构应用。近年来一度在大家项目中广泛使用。

由于 Redux 中放到的 combineReducers 和 reducer 中的 initialState
都为原生的 Object 对象,所以无法和 Immutable 原生搭配使用。

侥幸的是,Redux 并不排外使用 Immutable,能够团结重写 combineReducers
或行使 redux-immutablejs 来提供帮助。

上边我们提到 Cursor 能够方便寻找和 update 层级相比较深的数量,但因为 Redux
中曾经有了 select 来做检索,Action 来更新数据,因此 Cursor
在此地就未有用武之地了。

总结

Immutable
可以给使用带来巨大的属性提高,然而否利用还要看档次情状。由于侵入性较强,新品类引进相比便于,老项目搬迁供给评估迁移。对于部分提须求外部使用的国有组件,最棒不用把
Immutable 对象直接暴露在对外接口中。

比方 JS 原生 Immutable 类型会不会太美,被叫作 React API 终结者的
塞Bath蒂恩 马克båge
有八个这么的提案,能还是无法通过以往还不显著。然而能够肯定的是 Immutable
会被更加多的类型利用。

您恐怕感兴趣的篇章:

  • react质量优化达到最大化的主意
    immutable.js使用的要求性

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有