React-不可变数据的辅助工具
2016-02-25 13:21
696 查看
不可变数据的辅助工具(ImmutabilityHelpers)
React让你可以使用任何你想要的数据管理风格,包括数据可变风格。然而,如果你能够在你应用中讲究性能的部分使用不可变数据,就可以很方便地实现一个快速的shouldComponentUpdate()方法来显著提升你应用的速度。
在JavaScript中处理不可变数据比在语言层面上就设计好要难,像Clojure。但是,我们提供了一个简单的不可变辅助工具,update(),这就让处理这种类型的数据更加简单了,根本不会改变你数据的表示的形式。(Dealingwith
immutable data in JavaScript is more difficult than in languages designedfor it, like Clojure.
However, we've provided a simpleimmutability helper, update(), that makes dealing with this type of data much
easier,without fundamentallychanging how your data is represented.)
主要思想(The main idea)
如果你像这样改变数据:
myData.x.y.z=
7;
// or...
myData.a.b.push(9);
你无法确定哪个数据改变了,因为之前的副本被覆盖了。相反,你需要创建一个新的myDate副本,仅仅改变需要改变的部分。然后你就能够在shouldComponentUpdate()中使用第三方的相等判断来比较myData的旧副本和新对象:
var newData=deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
不幸的是,深拷贝是很昂贵的,而且某些时候还不可能完成。你可以通过仅拷贝需要改变的对象,重用未改变的对象来缓解这个问题。不幸的是,在当今的JavaScript里面,这会变得很笨拙:
var newData= extend(myData,{
x: extend(myData.x, {
y: extend(myData.x.y, {z:7}),
}),
a: extend(myData.a, {b: myData.a.b.concat(9)})
});
虽然这能够非常好地提升性能(因为仅仅浅复制log n个对象,重用余下的),但是写起来很痛苦。看看所有的重复书写!这不仅仅是恼人,也提供了一个巨大的出bug的区域。
update()在这种情形下提供了简单的语法糖,使得写这种代码变得更加简单。代码变为:
var newData=React.addons.update(myData, {
x: {y: {z: {$set:7}}},
a: {b: {$push: [9]}}
});
虽然这种语法糖需要花点精力适应(尽管这是受MongoDB's query language的启发),但是它没有冗余,是静态可分析的,并且比可变的版本少打了很多字。(Whilethe
syntax takes a little getting used to (though it's inspired by MongoDB's query language)
there's no redundancy, it'sstatically analyzable and it's not much more typing than the mutative version.)
以$为前缀的键被称作命令。他们“改变”的数据结构被称为目标。(
The $-prefixed keys arecalled commands.
The data structure they are "mutating" iscalled the target.)
可用的命令(Available commands)
{$push: array} 利用push()把目标上所有的元素放进数组(push() all
the items in array on the target.)。
{$unshift: array} 利用unshift()把目标上所有的元素放进数组(unshift() all
the items in array on the target.)。
{$splice: array of arrays} 依次使用 arrays 中的元素( array )作为参数,在目标对象( target )上调用 splice() 方法( Array.prototype.splice.apply(target,
array) )。
{$set: any} 整体替换目标(replace the target entirely.)。
{$merge: object} 合并目标和object的键。
{$apply: function} 传入当前的值到函数,然后用新返回的值更新它(passes in the current value to the function and updates
it with the new returned value.)。
示例
简单的入栈
var initialArray= [1,2,
3];
varnewArray=update(initialArray, {$push: [4]});//
=> [1, 2,3, 4]
initialArray仍然是[1, 2, 3]。
嵌入的集合
var collection= [1,2,
{a: [12,17,
15]}];
varnewCollection= update(collection, {2:
{a: {$splice: [[1,1,
13,14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]
获取collection中索引是2的对象,然后取得该对象键为a的值,删掉索引从1开始的一个元素(即移除17),插入13和14。(This
accesses collection's index 2,
key a, and does a spliceof one item starting from index 1 (to
remove 17) whileinserting 13and 14.)
根据现有的值更新
var obj= {a:5,
b:3};
varnewObj
=update(obj, {b: {$apply:function(x)
{return x*
2;}}});
// => {a: 5, b: 6}
// This is equivalent, but gets verbose fordeeply nested collections:
varnewObj2
=update(obj, {b: {$set: obj.b*
2}});
(浅)合并
var obj= {a:5,
b:3};
varnewObj
=update(obj, {$merge: {b:6,
c:7}});
// => {a: 5,b: 6, c: 7}
React让你可以使用任何你想要的数据管理风格,包括数据可变风格。然而,如果你能够在你应用中讲究性能的部分使用不可变数据,就可以很方便地实现一个快速的shouldComponentUpdate()方法来显著提升你应用的速度。
在JavaScript中处理不可变数据比在语言层面上就设计好要难,像Clojure。但是,我们提供了一个简单的不可变辅助工具,update(),这就让处理这种类型的数据更加简单了,根本不会改变你数据的表示的形式。(Dealingwith
immutable data in JavaScript is more difficult than in languages designedfor it, like Clojure.
However, we've provided a simpleimmutability helper, update(), that makes dealing with this type of data much
easier,without fundamentallychanging how your data is represented.)
主要思想(The main idea)
如果你像这样改变数据:
myData.x.y.z=
7;
// or...
myData.a.b.push(9);
你无法确定哪个数据改变了,因为之前的副本被覆盖了。相反,你需要创建一个新的myDate副本,仅仅改变需要改变的部分。然后你就能够在shouldComponentUpdate()中使用第三方的相等判断来比较myData的旧副本和新对象:
var newData=deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
不幸的是,深拷贝是很昂贵的,而且某些时候还不可能完成。你可以通过仅拷贝需要改变的对象,重用未改变的对象来缓解这个问题。不幸的是,在当今的JavaScript里面,这会变得很笨拙:
var newData= extend(myData,{
x: extend(myData.x, {
y: extend(myData.x.y, {z:7}),
}),
a: extend(myData.a, {b: myData.a.b.concat(9)})
});
虽然这能够非常好地提升性能(因为仅仅浅复制log n个对象,重用余下的),但是写起来很痛苦。看看所有的重复书写!这不仅仅是恼人,也提供了一个巨大的出bug的区域。
update()在这种情形下提供了简单的语法糖,使得写这种代码变得更加简单。代码变为:
var newData=React.addons.update(myData, {
x: {y: {z: {$set:7}}},
a: {b: {$push: [9]}}
});
虽然这种语法糖需要花点精力适应(尽管这是受MongoDB's query language的启发),但是它没有冗余,是静态可分析的,并且比可变的版本少打了很多字。(Whilethe
syntax takes a little getting used to (though it's inspired by MongoDB's query language)
there's no redundancy, it'sstatically analyzable and it's not much more typing than the mutative version.)
以$为前缀的键被称作命令。他们“改变”的数据结构被称为目标。(
The $-prefixed keys arecalled commands.
The data structure they are "mutating" iscalled the target.)
可用的命令(Available commands)
{$push: array} 利用push()把目标上所有的元素放进数组(push() all
the items in array on the target.)。
{$unshift: array} 利用unshift()把目标上所有的元素放进数组(unshift() all
the items in array on the target.)。
{$splice: array of arrays} 依次使用 arrays 中的元素( array )作为参数,在目标对象( target )上调用 splice() 方法( Array.prototype.splice.apply(target,
array) )。
{$set: any} 整体替换目标(replace the target entirely.)。
{$merge: object} 合并目标和object的键。
{$apply: function} 传入当前的值到函数,然后用新返回的值更新它(passes in the current value to the function and updates
it with the new returned value.)。
示例
简单的入栈
var initialArray= [1,2,
3];
varnewArray=update(initialArray, {$push: [4]});//
=> [1, 2,3, 4]
initialArray仍然是[1, 2, 3]。
嵌入的集合
var collection= [1,2,
{a: [12,17,
15]}];
varnewCollection= update(collection, {2:
{a: {$splice: [[1,1,
13,14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]
获取collection中索引是2的对象,然后取得该对象键为a的值,删掉索引从1开始的一个元素(即移除17),插入13和14。(This
accesses collection's index 2,
key a, and does a spliceof one item starting from index 1 (to
remove 17) whileinserting 13and 14.)
根据现有的值更新
var obj= {a:5,
b:3};
varnewObj
=update(obj, {b: {$apply:function(x)
{return x*
2;}}});
// => {a: 5, b: 6}
// This is equivalent, but gets verbose fordeeply nested collections:
varnewObj2
=update(obj, {b: {$set: obj.b*
2}});
(浅)合并
var obj= {a:5,
b:3};
varnewObj
=update(obj, {$merge: {b:6,
c:7}});
// => {a: 5,b: 6, c: 7}
相关文章推荐
- React-插件-性能分析工具
- React插件-测试工具集-克隆组件
- React Native-15.React Native 常用API及实践 AlertIOS AlertSheetIOS
- React插件-类名操作
- React插件-双向绑定辅助工具
- ReactiveCocoa入门
- react-native真机调试注意事项
- ReactiveCocoa 4 官方文档翻译
- React插件及动画插件
- React-native页面跳转传值实现
- (翻译)React.createClass对比extends React.Component
- iOS 第三方库 - ReactiveCocoa
- ReactiveCocoa框架菜鸟入门——信号(Signal)详解 第五课:适合给新手看的RAC用法总结
- ReactiveCocoa框架菜鸟入门——信号(Signal)详解 第四课
- ReactiveCocoa框架菜鸟入门——信号(Signal)详解 第三课:
- ReactiveCocoa框架菜鸟入门——信号(Signal)详解 第二课:信号(Signal)的各种操作
- ReactiveCocoa框架菜鸟入门——信号(Signal)详解 第一课:什么是 ReactiveCocoa
- React Native for Android 学习笔记(一) 操蛋的环境搭建与demo运行
- React-Native 原生模块(iOS)调用
- 初识Android的ReactiveX