react性能优化

若是想提升性能就须要知道什么地方会影响性能?

从过往的经验和实践中,影响网页性能最大的因素就是浏览器的重绘和回流,React背后的虚拟DOM就是尽量的减小浏览器的重绘和回流。react

那在此之上,咱们还能作什么来防止没必要要的渲染?编程

在这以前,先跟我一块儿了解下***函数式编程***数组

什么是函数式编程?

函数式编程起源于数学,假设咱们定义一个加法的方法f,而后改变输入为f(1,3),那么不管这个方法的上下文,不管什么时间调用多少次,返回结果都是4,用数学表达就是f(x,y) = z,给定输入x,y做用在f上,始终结果是z浏览器

函数式编程讲究的三个原则:
1.相同的输入获得相同的输出
2.没有反作用
3.不依赖外部的状态(方法内的状态都只在方法的生命周期内存活,不能在方法中使用共享变量,由于这样会给方法带来不可知对的因素)性能优化

那说了这么多函数式编程有什么好处呢?

一、函数式编程不依赖外部状态这一特色,使得咱们能够利用CPU在分布式集群上作并行计算,这对于多种科学计算和资源密集型计算任务是很是核心的一点,让计算机高效处理这类任务变更的可能 二、相同的输入获得相同对的输出,这让咱们的代码变得可预测,能够很是方便的进行方法级别的测试。bash


说完函数式编程,咱们再回头说说react的性能优化 《深刻React技术栈中》这样描述的“ react的设计是有函数式编程的基因的,react组件自己就是纯函数,react的createElement方法保证了组件是纯净的,即传入相同的props获得必定的虚拟dom,整个过程可预测”。
那么优化的时候咱们能够考虑经过拆分组件为子组件,进而对组件进行更细粒度的控制。数据结构


那接下来就要考虑如何作更细粒度控制,避免屡次无用渲染?

react官方有提供PureComponent类,凡是继承自这个类的组件,react都会默认在shouldComponentUpdate中替你作这样一件事,浅比较你的新传入的props和state是否和如今的props,state。所谓的浅比较就是只比较props和state中数据的引用地址,引用地址不改变就不会从新渲染。dom

很显然,问题来了,若是个人数据结构嵌套很深,那岂不是会忽略掉深层次的数据变化,而致使页面不渲染? 所以react官方提醒道,继承PureComponent以前最好props,state的结构简单,对于嵌套深的结构就不要继承PureComponent了分布式


那对于深层次的数据结构就这样放弃使用puerRender了吗?答案固然不是了,不过先不急着说这个,咱们先说对于结果简单的能够继承PureComponent的咱们要注意些什么?函数式编程

<MeetingList style = {{'width':'200px','height':'200px','overFlow':'hidden'}}>
  
  <Item items = {this.props.items.filter(item=>item.val>10)}>
复制代码

这种直接将props设置成对象或者数组的方式,每次都会触发从新渲染,哪怕值没有改变。

缘由在于每次调用react组件都会从新建立组件,就算传入的数组或对象值没有改变,可是引用地址发生改变了。

解决方法,将对象提早赋值为常量,不直接使用字面量便可 二、

<input onChange = this.change.bind(this)>
复制代码

设置props方法并经过bind绑定this的方式,每次都会触发从新渲染

缘由在于bind会返回一个函数,每次执行bind返回的函数的引用地址改变了

解决办法采用箭头函数

三、

class NameItem extends Component {
    render(){
        return (
        <Item >
         <span>a child</span>
         </Item>
        )
    }
}
 
复制代码

对于设置了子组件的react组件,每次都会从新渲染。

缘由在于,组件编译以后实际上是这样的

<Item children = {React.createElement('span',{},'a child')}>
复制代码

children引用改变了,致使每次都会从新渲染

解决办法让NameItem(也就是Item的父组件)继承pureComponent,根据浅比较策略不会对Item的children进行深比较,也就不会从新渲染


说完简单的数据结构,咱们再来讲下对于props和state比较复杂的数据结构应该怎么处理,答案是采用immutable。

简单说下immutable
持久化数据存储:对immutable对象进行修改的时候都会返回一个新的immutable对象,也就是使用旧数据建立新数据时,包证了旧数据可用 结构化共享:若是树中一个节点变化,则只修改这个节点和受它影响的父节点,其余节点实现共享,避免了深拷贝带来的性能问题

如何使用immutable实现pureRender?

答案是在shouldComponentUpdate中利用immutable进行深比较,抛弃以前的PureComponent的浅比较

import React from 'react';
import {is} from 'immutable';

class App extends Component {
 shouldComponentUpdate(nextProps,nextState){
   const thisProps = this.props || {};
   const thisState = this.state || {};
   if(Object.keys(thisProps).length !== Object.keys(nextProps.keys).length ||
   Object.keys(thisProps).length !== Object.keys(nextProps.keys).length){
       return true;
   }

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

   for(const key in nextState){
     if(nextState.hasOwnProperty(key) && !is(thisState[key],nextState[key])){
       return true;
     }
   }

   return false;

 }
}
复制代码