ReactJS学习系列课程(React 性能优化及immutable使用)

来源:互联网 发布:flac转wav软件 mac 编辑:程序博客网 时间:2024/04/23 20:10

这里写图片描述

一个框架的性能,往往使我们比较关注的问题,对于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);  // 打印 aisonconsole.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 取值,打印 richardconsole.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 一样取值,打印 richardconsole.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。

所以大家在使用过程中,应该仔细斟酌,看情况而定。

0 0