ifyour / learn-react

🤠 React learning notes
MIT License
6 stars 0 forks source link

React 优化进阶 #8

Open ifyour opened 6 years ago

ifyour commented 6 years ago

优化点

  1. 组件性能优化

    • 1.1 属性传递优化
    • 1.2 多组件优化
    • 1.3 key 的使用
    • 1.4 shouldComponentUpdate
    • 1.5 pureComponent
    • 1.6 不可变数据优化
  2. Redux 性能优化

    • 2.1 reducer 纯函数
    • 2.2 reselect: 缓存上次的计算结果
    • 2.3 React 同构: 首屏服务端渲染

一些实例

/**
 * 属性传递优化, 不传递不必要的属性, 不执行不必要的方法
 */

// 写法1: 组件每一次 render, bind 都会执行一次
<button onClick={ this.handleClick.bind(this) }>btn1</button>

// 写法2: 每一次执行 render 的时候, 都要生成一个函数
<button onClick={ () => this.handleClick() }>btn2</button>

// 所以最优的写法是在 constructor 中去声明一次:
class Demo extends React.Component {
  constructor(props) {
    super(props);
    // 构造函数中只执行一次
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    console.log('You click me!');
  }
  render() {
    return (
      <button onClick={ this.handleClick }>ClickMe</button>
    )
  }
}

// 写法3: 使用组件的时候传递属性, 每次都新生成了一个对象
<Demo style={ {color: 'red'} } />

// 这样写好点
const style = { color: 'red' }
<Demo style={ style } />
/**
 * 多组件优化, 避免重复 render
 */

class App extends React.Component {
  state = {
    count: 0
  }

  inc = () => this.setState({
    count: this.state.count + 1
  })

  dec = () => this.setState({
    count: this.state.count - 1
  })

  render() {
    return (
      <div>
        <h2>{this.state.count}</h2>
        <button onClick={this.inc}>Increment</button>
        <button onClick={this.dec}>Decrement</button>
        <Demo title="title" />
      </div>
    )
  }
}

class Demo extends React.Component {
  // 通过这个方法来判断组件是否需要更新
  // 此方法始终返回一个布尔值, 确定是否走更新流程
  // 可以理解为一个漏斗
  shouldComponentUpdate(nextProps, nextState) {
    // console.log('currentProps:',this.props.title);
    // console.log('nextProps:', nextProps);
    return this.props.title !== nextProps.title;
  }

  render() {
    console.log('Demo render !');
    return <h2>Demo H2 :{this.props.title}</h2>
  }
}

ReactDOM.render(<App />, document.getElementById('app'))
/**
 * Keys 可以在 DOM 中的某些元素被增加或删除的时候
 * 帮助 React 识别哪些元素发生了变化, 设一个唯一值来提升渲染效率
 */

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);
/**
 * 使用 PureComponent 来渲染一些无状态组件
 * 比如纯粹根据 props 来渲染的一些组件
 */

// 上面的 Demo 可以这样优化写更好
class Demo extends React.PureComponent {
  render() {
    return <h2>Demo H2 :{this.props.title}</h2>
  }
}
/**
 * 异步处理多次渲染的解决方案
 */

componentWillReceiveProps(nextProps) {
  if (isEqual(this.props, nextProps)) {
    return
  }

  // ...

  this.setState({ ... })
}

shouldComponentUpdate(nextProps, nextState) {
  return !isEqual(nextProps, this.props) || !isEqual(nextState, this.state);
}

TODO...