组件的性能优化 - 01.单组件性能优化

组件的性能优化 - 01.单组件性能优化

本文主要关注在React组件的性能优化的相关知识和原理上,便于对React单组件的性能优化方式有一定的认识和了解

属性传递优化

React的单组件性能优化主要是聚焦在属性传递的优化上,属性传递优化的核心在于Javascript的赋值的本质是引用赋值。
在Javascript中,{a: 1} !== {a: 1},因为他们在内存中的地址并不相等,如果每次在组件渲染阶段,都为属性赋值创建新的对象,必然会造成性能开销。

属性传递优化的主要关注点在:

  • 函数传递的优化
  • 属性传递优化

函数传递优化

在React中,函数赋值为了解决this指向的问题,主要有以下三种形式:

  1. 通过在构造函数中this.handleClick = this.handleClick.bind(this),并在模板中使用<button onClick="{this.handleClick}">Button</button>
  2. 在模板中使用bind方法<button onClick="{this.handleClick.bind(this)}">Button</button>
  3. 在模板中使用箭头函数<button onClick="{() => this.handleClick}">Button</button>

这其中推荐使用方式1,不推荐使用方式2、3。因为在构造函数中调用this.handleClick.bind()只会进行一次赋值,而在方法2中,在模板中调用的话,每次render渲染都会调用this.handleClick.bind创建一个新的函数句柄,方法3同理

属性传递优化

在React的‘模板’中,属性传值的过程中,并不推荐使用<Demo style="{{color: red}}" skill="{{name: 'react'}}"/>的方式进行值创建并传值,原因同上,即在每次调用react方法的时候都会创建新的对象{color: 'red'},通常将页面中不需要不变化的属性传递放置在constructor中进行。
其次,在React中也并不推荐盲目使用扩展运算符,进行传值。(result="{...this.state}"),原因在于,子组件中并不需要全部值的时候,使用扩展运算符将对象属性完整透传到子组件中也会造成多余的性能开销。

示例:

import React, {Component} from 'react';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      num: 1,
      age: 20,
      title: '单组件性能优化',  
    }
    console.log('构造函数执行中')
    this.handleClick = this.handleClick.bind(this)
    this.skill = {name: 'react'}
  }

  handleClick () {
    this.setState({
      num: this.state.num + 1
    })
  }

  render () {
    console.log('渲染函数执行中')
    return (
      <div>
        <section>
          <p>
            <mark>推荐使用这种函数传递的方式,因为该函数只会在构造函数中执行一次</mark>  
          </p>
          <button onClick={this.handleClick}>button01</button>
        </section>
        <section>
          <p>
            <mark>以下两种函数传递的方式,均不是非常推荐,他们都会在组件的渲染阶段,重新生成调用函数,对性能造成一定的影响</mark>
          </p>
          <button onClick={this.handleClick.bind(this)}>button02</button><br/>
          <button onClick={() => this.handleClick}>button03</button>
        </section>
        <br></br>
        <mark>这种传值方式也不推荐,因为每次都会在渲染阶段生成一个新的对象,从而造成性能开销</mark>
        <Demo style={{color: 'red'}} skill={{name: 'react'}}></Demo>
        <Demo style={{color: 'red'}} skill={this.skill}></Demo>
        <mark>不推荐的传值方式,如果组件中只需要属性title,而扩展运算符会将state中额外的属性一并传递给组件,从而造成性能开销</mark>
        <Demo {...this.state} skill={{name: 'react'}}></Demo>
      </div>
    )
  }
}

function Demo (props) {
  return (
    <div>
      <h2>I am a Demo</h2>
      <h3>{props.title}</h3>
      <h3>{props.skill.name}</h3>
    </div>
  )
}

export default App;

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 8,529评论 1 33
  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,107评论 2 35
  • 函数是面向过程的,函数的调用不需要主体,而方法是属于对象的,调用方法需要一个主体-即对象。 npm install...
    Gukson666阅读 480评论 0 3
  • 40、React 什么是React?React 是一个用于构建用户界面的框架(采用的是MVC模式):集中处理VIE...
    萌妹撒阅读 1,059评论 0 1
  • GUIDS 第一章 为什么使用React? React 一个提供了用户接口的JavaScript库。 诞生于Fac...
    jplyue阅读 3,595评论 1 11