ReactJS学习系列课程(React 性能优化及immutable使用)
2016-06-28 14:18
841 查看
一个框架的性能,往往使我们比较关注的问题,对于React性能提升的问题,也做了相关研究,最近网络上最火爆的当属Immutable, 有人说 Immutable 可以给 React 应用带来数十倍的提升,也有人说 Immutable 的引入是近期 JavaScript 中伟大的发明。
这是一个Facebook 工程师 Lee Byron 花费 3 年时间打造,与 React 同期出现, 那么这个library的牛逼之处,到底在哪里呢?
影响性能的关键:
我们都知道Javascript中的对象一般都是可变的,因为多数都是引用赋值,比如下面的例子:let person1 = {name: 'richard', age: 25}; person2 = person1; person2.name = Aison;
上面的例子中,你会发现person1.name也被修改成了Aison,其实这样也没什么不好的,对于一个SPA应用来讲还是可选的,因为一定程度上节约了内存的开销,可以如果对于大型的长期项目而言,不一定就是好事了,往往会有很大的隐患,会无意中造成数据的更换, 对于一个老程序员来说,往往会做一个深拷贝,或者浅拷贝,但是拷贝这种方式在一定程度上造成了cpu和系统内存的浪费,而immutable得出现,恰恰是为了解决这一个问题的出现。
immutable的定义
从字面意义上来讲,就是不可变的数据, 对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享, 如下图:图片来源(http://img.alicdn.com/)
immutable支持框架
目前github上有两款开源开源,一个是immutable.js, 另一个是seemless-immutable.js。对于immutable.js是Facebook工程师创造的,是一套完整的持久化数据结构,但是这个库并没有被纳入react当中,它包含了很多可用变量和函数,比如Collection、List、Map、Set、Record、Seq, 我们常用的数据结构比如set, map , list,这个很想java。
而seamless-immutable 并没有实现完整的 Persistent Data Structure,而是使用 Object.defineProperty(因此只能在 IE9 及以上使用)扩展了 JavaScript 的 Array 和 Object 对象来实现,只支持 Array 和 Object 两种数据类型,所有使用过程中大家看情况而定。
immutable如何使用
对于如何使用immutable才是我们更加关注的要点,因为我们需要实际应用到我们的项目当中。我们先看一段代码:
// 原来的写法 let myClass1 = {classmates: {name: 'richard'}}; let myClass2 = myClass1; myClass2.classmates.name = 'aison'; console.log(myClass1.classmates.name); // 打印 aison console.log(myClass2 === myClass1); // 打印 true // 使用 immutable.js 后 import Immutable from 'immutable'; myClass1 = Immutable.fromJS({classmates: {name: 'richard'}}); myClass2 = myClass1.setIn(['classmates', 'name'], 'aison'); // 使用 setIn 赋值 console.log(foo.getIn(['classmates', 'name'])); // 使用 getIn 取值,打印 richard console.log(myClass1 === myClass2); // 打印 false // 使用 seamless-immutable.js 后 import SImmutable from 'seamless-immutable'; myClass1 = SImmutable({classmates: {name: 'richard'}}) myClass2 = foo.merge({classmates: {name: 'aison'}}) // 使用 merge 赋值 console.log(myClass1.classmates.name); // 像原生 Object 一样取值,打印 richard console.log(myClass1 === myClass2); // 打印 false
与 React 搭配使用
熟悉 React 的都知道,React 做性能优化时有一个避免重复渲染的大招,就是使用 shouldComponentUpdate(),但它默认返回 true,即始终会执行 render() 方法,然后做 Virtual DOM 比较,并得出是否需要做真实 DOM 更新,这里往往会带来很多无必要的渲染并成为性能瓶颈。当然我们也可以在 shouldComponentUpdate() 中使用使用 deepCopy 和 deepCompare 来避免无必要的 render(),但 deepCopy 和 deepCompare 一般都是非常耗性能的。
Immutable 则提供了简洁高效的判断数据是否变化的方法,只需 === 和 is 比较就能知道是否需要执行 render(),而这个操作几乎 0 成本,所以可以极大提高性能。修改后的 shouldComponentUpdate 是这样的:
import { is } from 'immutable'; shouldComponentUpdate: (nextProps, nextState) => { return !(this.props === nextProps || is(this.props, nextProps)) || !(this.state === nextState || is(this.state, nextState)); }
在setState过程中,如果我们不希望改变原有的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')); }
总结
以上就是React优化的简单使用,对于immutable,个人感觉对于手机来讲,库很大,对于seemless-immutable来讲功能又太少,而且,一但使用,会遍布在项目的很多地方,融合度比较高,但是性能的提升还是很大的,尤其是react。所以大家在使用过程中,应该仔细斟酌,看情况而定。
相关文章推荐
- 超级给力的JavaScript的React框架入门教程
- JavaScript的React框架中的JSX语法学习入门教程
- 由ReactJS的Hello world说开来
- 深入探讨前端框架react
- 深入浅析react native es6语法
- Windows下React Native的Android环境部署及布局示例
- 深入理解JavaScript的React框架的原理
- 在React框架中实现一些AngularJS中ng指令的例子
- H5、React Native、Native应用对比分析
- react Native 运行程序报错解决笔记
- CSS Modules 详解及 React 中实践
- webpack共用于前后端的小坑
- 初体验react的状态机
- 比较react和flex的设计哲学
- React 相关文档
- 在现有 server 中集成 webpack + react 热加载
- React Native 的那些坑
- 7月国外最新技术文章翻译汇总(IT技术)