You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
当我们说一个 React component 是 pure render,是指它的 render function 是 pure function。
Pure render 的好处之一就是可以在 shouldComponentUpdate 中做性能优化。最常見的做法就是用 shallow equal 检查 props 和 state 有无改变,有改变才 update component。
shouldComponentUpdate
当一个 React 组件的 props 和 state 发生变化时,React 会根据变化后的 props 和 state 创建一个新的 virtual DOM,然后比较新旧两个 vritual DOM 是否一致,只有当两者不同时,React 才会将 virtual DOM 渲染真实的 DOM 结点,而对 React 进行性能优化的核心就是减少渲染真实 DOM 结点的频率,间接地指出开发者应该准确判断 props 和 state 是否真正发生了变化。
importImmutablefrom'immutable';const{ List }=Immutable;constarr1=List([1,2,3]);constarr2=arr1.set(-1,7);//set(index: number, value: T)constarr3=arr1.insert(1,2);// insert(index: number, value: T)constarr4=arr1.clear();console.log(arr1);// List [1, 2, 3 ]console.log(arr1.size);//3console.log(arr2);// List [1, 2, 7 ]console.log(arr3);// List [1,2,2,3]console.log(arr4);// List []
set
无序列表,且不能重复。类似于ES6的Set
importImmutablefrom'immutable';const{ Set }=Immutable;constset1=Set([1,2,3]);constset2=set1.add(1).add(5);constset3=set1.delete(3);constset4=Set([2,3,4,5,6]);console.log(set1);// Set { 1, 2, 3 }console.log(set2);// Set { 1, 2, 3, 5}console.log(set3);// Set {1, 2}console.log(set4);// Set{2,3,4,5,6}console.log(set1.intersect(set4));// 取交集 Set {3,2}console.log(set1.subtract(set4));// 取差集 Set { 1 }
is
与Object.is()类似,都是对值的比较
importImmutablefrom'immutable';const{ is }=Immutable;console.log(is([1,2,3],[1,2,3]));//falseconsole.log(is('hello','hello'));//trueconsole.log(is(0,'0'));//falseconsole.log(is({name: 'react'},{name: 'react'}));//falseletmap1=Immutable.Map({a:1,b:1,c:1});letmap2=Immutable.Map({a:1,b:1,c:1});console.log(is(map1,map2));// true
实例
React推荐将初始state设为Immutable:
importReactfrom'react'import{List,Map}from'immutable';classImmutableItemextendsReact.Component{constructor(props){super(props);this.state={data: Map({count: 0,items: List()})}this.handleCountClick=this.handleCountClick.bind(this)this.handleAddItemClick=this.handleAddItemClick.bind(this)}handleCountClick(){this.setState(({ data })=>({data: data.update('count',v=>v+1)// 提供一个返回状态更新的函数,用新的不可变数据更新React 状态}))}handleAddItemClick(){this.setState(({ data })=>({data: data.update('items',list=>list.push(data.get('count')))}));}render(){constdata=this.state.data;return(<div><buttononClick={this.handleCountClick}>Add to count</button><buttononClick={this.handleAddItemClick}>Save count</button><div>
Count: {data.get('count')}</div>
Saved counts:
<ul>{data.get('items').map((item,index)=><likey={index}>Saved: {item}</li>)}</ul></div>);}}exportdefaultImmutableItem
The text was updated successfully, but these errors were encountered:
什么是
Immutable Data
Immutable Data 顾名思义就是一旦创建就不能再被更改的数据。在js中实现数据不可变,有两个方法:
const(es6)
Object.freeze(es5)
但是这两种方法都是shallow处理,遇到嵌套深的结构就需要递归处理,深度拷贝的坏处很明显,即对象越复杂,性能开销越大。在JavaScript中,对象默认是可变的。当你复制一个对象时,JavaScript不得不复制每一个属性来保证这两个对象相互独立。当数据量及其庞大的时候,这种性能的瓶颈就显而易见了。
Immutable data
及其原理Immutable 实现的原理是
Persistent Data Structure
(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。1.
structural sharing
结构共享当我们对一个
Immutable
对象进行操作的时候,ImmutableJS基于哈希映射树(hash map tries)和vector map tries,只clone该节点以及它的祖先节点,其他保持不变,这样可以共享相同的部分,大大提高性能。在React.js中使用
Immutable Data
PureRenderMixin
当我们说一个
React component
是pure render
,是指它的render function
是pure function
。Pure render 的好处之一就是可以在
shouldComponentUpdate
中做性能优化。最常見的做法就是用 shallow equal 检查 props 和 state 有无改变,有改变才update component
。而React 中自带的
PureRenderMixin
也只是简单的浅比较,不能用于深层比较:Immutable 可以给 React 应用带来数十倍的性能提升,数据的不可变性使得追踪变化的开销变小,当state更新时,如果数据没变,React也会去做
virtual dom
的diff,这就产生了浪费。shouldComponentUpdate
当一个 React 组件的 props 和 state 发生变化时,React 会根据变化后的 props 和 state 创建一个新的 virtual DOM,然后比较新旧两个 vritual DOM 是否一致,只有当两者不同时,React 才会将 virtual DOM 渲染真实的 DOM 结点,而对 React 进行性能优化的核心就是减少渲染真实 DOM 结点的频率,间接地指出开发者应该准确判断 props 和 state 是否真正发生了变化。
然而,
shouldComponentUpdate
也只能进行shadow compare,当比较的值是数组或者对象时,这种方式就不work了,如果数据是 Immutable Data 的话,那么数据发生变化就会生成新的对象,开发者只需要检查对象应用是否发生变化即可。
Immutable 则提供了简洁高效的判断数据是否变化的方法,只需 === 和 is 比较就能知道是否需要执行 render(),而这个操作几乎 0 成本,所以可以极大提高性能。
函数式编程
Immutable 本身就是函数式编程中的概念,纯函数式编程比面向对象更适用于前端开发。因为只要输入一致,输出必然一致,这样开发的组件更易于调试和组装。通常对于非常简单的组件,我们通常可以使用函数组件:
但是函数组件也是一个 React 组件,当使用时,也会在内部调用
componentWillMount
、componentDidMount
、componentWillUnmount
等生命周期函数。为了提高性能,我们可以将其作为函数调用,而不是React组件调用。
改成函数调用后,没有生成
React.createElement
,也就没有了 React 组件的生命周期函数。函数式编程的几大概念:
1.函数是一等公民
2.数据是不可变的
3.强制使用纯函数(没有任何副作用,输出完全由输入决定
4.函数只接受一个参数(科里化
5.函数 无状态
Immutable 可以让代码更容易维护,在js操作数组和对象的原生方法中,很容易违反这种原则,例如:
数组中会改变原数组的方法有:
也不要直接去修改一个对象的字段:
函数只接受一个参数,也就是函数的科里化,例如在Redux中middleware的实现:
Immutable API
对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。
Immutable.fromJS
可以将普通的js对象深层次的转化为Immutable
对象 (Object=>Map,Array=>List)Immutable.Map
只能浅层次的转化为immutable对象map2包含了更新后的数据,而map1数据依然保持不变。任何数据的修改都不影响最原始的数据,在让我们在引用数据的时候毫无后顾之忧
有序索引集,类似于 JavaScript 中的 Array
无序列表,且不能重复。类似于ES6的Set
与
Object.is()
类似,都是对值的比较实例
React推荐将初始state设为Immutable:
The text was updated successfully, but these errors were encountered: