通过Pure Render和Immutable实现React中的性能优化

简介:

简要介绍:React中的render存在着不必要的渲染,可以通过Puer Render(PureComponent)来减少渲染的次数,但是Puer Render只是进行浅比较,无法实现深层对象上的性能优化。Pure Render结合Immutable可以减少渲染次数。

1 . React中的render

仅通过React中的render,存在着不必要的渲染,这种不必要的渲染分为两大类。

(1)自身的state没有改变

在React的render中,只要发生setState行为,就会去重新渲染,即使setState的属性前后并没有发生变化,比如:

class TestComponent extends React.Component{
  constructor(props){
    super(props);
    this.state={
      count:0
    }
  }
  componentDidMount(){
    let self=this;
    setTimeout(function(){
      self.setState({
        count:0
      })
    },1000)
  }
  componentDidUpdate(){
    console.log('组件更新了');
  }
  render(){
    return <div>1</div>
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在这个组件中,我们setState的值在前后并没有发生改变,但是调用此组件会输出:

//组件更新了
  • 1

说明只要setState发生了,即使值在前后没有发生变化,组件也会重新render。

(2)父组件传递的props会引起所有子组件render

父组件中的值传递给子组件,即使某些子组件中不需要重新渲染,也会重新render。举例来说,父组件为Father:

class Father extends React.Component{
  constructor(props){
    super(props);
    this.state={
      obj:{
        title:'test immutable',
        childZero:{
          name:'childZero',
          age:0
        },
        childOne:{
          name:'childOne',
          age:1
        },
        childTwo:{
          name:'childTwo',
          age:2
        }
      }
    }
  }
  componentDidMount(){
    let self=this;
    let {obj}=this.state;
    setTimeout(function(){
      self.setState({
        obj:obj
      })
    },1000)
  }
  render(){
    const {obj}=this.state;
    return <div>
             <ChildZero obj={obj}/>
             <ChildOne obj={obj}/>
             <ChildTwo obj={obj}/>
           </div>
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

父组件有3个子组件:

class ChildZero extends React.Component{
  constructor(props){
    super(props);
  }
  componentDidUpdate(){
    console.log('childZero触发了更新')
  }
  render(){
    return <div>3</div>
  }
}
class ChildOne extends React.Component{
  constructor(props){
    super(props);
  }
  componentDidUpdate(){
    console.log('childOne触发了更新')
  }
  render(){
    return <div>3</div>
  }
}
class ChildTwo extends React.Component{
  constructor(props){
    super(props);
  }
  componentDidUpdate(){
    console.log('childTwo触发了更新')
  }
  render(){
    return <div>3</div>
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

我们在父组件的componentDidMout方法中,setState然后观察子组件的更新情况,发现所有的子组件都会更新,具体输出为:

//childZero触发了更新
//childOne触发了更新
//childTwo触发了更新
  • 1
  • 2
  • 3

2 . Pure Render可以减少浅层对象上不必要的更新

通过定义组件为Pure Render可以通过浅层比较,减少不必要的更新。我们通过使用PureComponent。同样的我们以1(1)中的为例:

class TestComponent extends React.PureComponent{
  constructor(props){
    super(props);
    this.state={
      count:0
    }
  }
  componentDidMount(){
    let self=this;
    setTimeout(function(){
      self.setState({
        count:0
      })
    },1000)
  }
  componentDidUpdate(){
    console.log('组件更新了');
  }
  render(){
    return <div>1</div>
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

通过PureComponent来代替Component,此时如果仅仅是浅层对象属性,当setState前后属性不变时,那么就不会有不必要的渲染。但是对于深层对象而言,pure Render无法实现。

3 .通过Immutable实现深层对象的性能优化

Immutable实现了js中的不可变数据结构,immutable具有不可变性,持久性等特点,通过数据共享的方式,修改相应的属性实现深度克隆的过程只会影响父类属性。

通过immutablejs可以方便进行深层对象的“相等”判断。在React的性能优化中,在生命周期函数shouldComponetUpdate中判断在是否需要更新,进行前后props和前后state的深层比较。

shouldComponentUpdate(nextProps,nextState){
    //进行深层判断使用immutable
    const thisProps=this.props;
    if(Object.keys(thisProps).length!==Object.keys(nextProps).length){
      return true;
    }

    for(const key in nextProps){
      console.log(is(thisProps[key],nextProps[key]));
      if(!is(thisProps[key],nextProps[key])){
        return true;
      }
    }
    return false;
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

如果返回true,那么会进行render,如果返回false,就不会render,从而可以控制深层对象是否需要重新render,实现了性能的优化。

这里使用immutable,主要是因为其拥有如下特点:

I)快,在深层对比对象(Map)或者数组(List)是否相同,比深层克隆式的比较快

II)安全,指的是对所有immutable的增删改查,都是增量,不会使得原始数据丢失

3.immutable的缺点

使用immutalbe也存在了一些缺点:

(1)immutablejs源文件较大

(2)具有很强的侵入性

本文作者:小小小小小亮
本文发布时间:2018年04月20日
本文来自云栖社区合作伙伴 CSDN,了解相关信息可以关注csdn.net网站。
目录
相关文章
|
5月前
|
前端开发
react-router中的render、children、component
react-router中的render、children、component
160 1
|
13天前
|
前端开发 JavaScript UED
深入React Hooks与性能优化实践
深入React Hooks与性能优化实践
23 0
|
5月前
|
前端开发 API 开发者
你可能没有关注过的 React 性能优化,帮你突破瓶颈
你可能没有关注过的 React 性能优化,帮你突破瓶颈
|
2月前
|
XML 前端开发 JavaScript
React 中render()的用途是什么?
【8月更文挑战第30天】
48 1
|
2月前
|
开发者 搜索推荐 Java
超越传统:JSF自定义标签库如何成为现代Web开发的个性化引擎
【8月更文挑战第31天】JavaServer Faces(JSF)框架支持通过自定义标签库扩展其内置组件,以满足特定业务需求。这涉及创建`.taglib`文件定义标签库及组件,并实现对应的Java类与渲染器。本文介绍如何构建和应用JSF自定义标签库,包括定义标签库、实现标签类与渲染器逻辑,以及在JSF页面中使用这些自定义标签,从而提升代码复用性和可维护性,助力开发更复杂且个性化的Web应用。
48 0
|
2月前
|
前端开发 测试技术 UED
React性能优化的神奇之处:如何用懒加载与代码分割让你的项目一鸣惊人?
【8月更文挑战第31天】在现代Web开发中,性能优化至关重要。本文探讨了React中的懒加载与代码分割技术,通过示例展示了如何在实际项目中应用这些技术。懒加载能够延迟加载组件,提高页面加载速度;代码分割则将应用程序代码分割成多个块,按需加载。两者结合使用,可以显著提升用户体验。遵循合理使用懒加载、编写测试及关注性能等最佳实践,能够更高效地进行性能优化,提升应用程序的整体表现。随着React生态的发展,懒加载与代码分割技术将在未来Web开发中发挥更大作用。
36 0
|
2月前
|
缓存 前端开发 JavaScript
React.memo 与 useMemo 超厉害!深入浅出带你理解记忆化技术,让 React 性能优化更上一层楼!
【8月更文挑战第31天】在React开发中,性能优化至关重要。本文探讨了`React.memo`和`useMemo`两大利器,前者通过避免不必要的组件重渲染提升效率,后者则缓存计算结果,防止重复计算。结合示例代码,文章详细解析了如何运用这两个Hook进行性能优化,并强调了合理选择与谨慎使用的最佳实践,助你轻松掌握高效开发技巧。
42 0
|
2月前
|
前端开发 测试技术
React 中 Render Prop 的概念
【8月更文挑战第31天】
23 0
|
3月前
|
缓存 监控 前端开发
react 性能优化方案?
【7月更文挑战第15天】改善React应用性能的关键策略包括:使用生产环境构建减少体积,避免不必要的渲染(如用React.memo或PureComponent),正确设置列表渲染的key,简化组件层级,实施懒加载,避免render中的复杂计算,选择优化过的库,控制重渲染范围,监控性能并合并state更新。这些优化能提升响应速度和用户体验。
33 0
|
5月前
|
前端开发 数据可视化 UED
React的代码分割:使用React.lazy和Suspense进行性能优化
【4月更文挑战第25天】使用React的`React.lazy`和`Suspense`进行代码分割可优化性能,按需加载组件以提升应用启动速度和用户体验。`React.lazy`接收返回Promise的组件动态导入,而`Suspense`提供加载指示器,保证加载过程中的用户体验。适用于大型组件或路由应用,但需注意服务器配置、避免过度拆分和确保关键代码即时加载。合理运用能显著改善应用性能。