Skip to content

Fragment

react 组件中只能有一个根组件.

之前使用 div 包裹的方式会给 html 结构增加很多无用的层级

为了解决这个问题,可以使用 React.Fragment

javascript
function Hello() {
  return (
    // 渲染到页面之后,这个div就是一个多余的
    <div>
      <h1>fragment</h1>
      <p>hello react</p>
    </div>
  );
}
// 将上面的写法,修改为下面的写法
function Hello() {
  return (
    // 这样就只会渲染h1和p
    <React.Fragment>
      <h1>fragment</h1>
      <p>hello react</p>
    </React.Fragment>
  );
}

// 简写形式
function Hello() {
  return (
    // 这是React.Fragment的简写形式
    <>
      <h1>fragment</h1>
      <p>hello react</p>
    </>
  );
}

React 性能优化

  • 减轻 state 跟页面渲染无关的数据,不要放在 state 中(比如定时器的 id.不要放在 state 中)

    • 可以有效减少页面重新渲染次数
  • shouldComponentUpdate (减轻不必要的重新渲染)

    • **组件更新的机制: **父组件重新渲染时,也会重新渲染子组件

    • 如何避免不必要的重新渲染呢?

    • 解决方式:使用钩子函数 shouldComponentUpdate(nextProps, nextState)

    • 作用:通过返回值决定该组件是否重新渲染,返回 true 表示重新渲染,false 表示不重新渲染

    • 触发时机:更新阶段的钩子函数,组件重新渲染前执行 (shouldComponentUpdate => render)

    javascript
    // 父组件
    class Far extends Component {
      state = {
        num: 0,
      };
      // 返回min~max之间的随机整数(包含min和max)
      getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
      }
      handle = () => {
        let num = this.getRandomIntInclusive(1, 3);
        this.setState({
          num,
        });
      };
      //有效减少组件渲染次数
      shouldComponentUpdate(props, state) {
        // this.state 原来的state
        // state 最新的state
        return this.state.num !== state.num;
      }
      render() {
        console.log("父组件渲染了");
        return (
          <div>
            <h1 onClick={this.handle}>Far组件</h1>
            <p>{this.state.num}</p>
            <Son num={this.state.num}></Son>
          </div>
        );
      }
    }
    
    // 不管子组件有没有用到父组件的数据,只要父组件重新渲染了,子组件就会跟着渲染
    
    // 子组件
    class Son extends Component {
      //有效减少组件渲染次数
      shouldComponentUpdate(props, state) {
        // this.props 原来的props
        // props 最新的props
        return props.num !== this.props.num;
      }
      render() {
        console.log("Son组件渲染了");
        return (
          <div>
            <h1>Son组件</h1>
            <p>{this.props.num}</p>
          </div>
        );
      }
    }
  • 纯组件 pureComponent

    • PureComponent 与 React.Component 功能相似,直接替换即可

    • 区别:PureComponent 内部自动实现了 shouldComponentUpdate 钩子,不需要手动比较

    • 原理:纯组件内部通过分别 对比 前后两次 props 和 state 的值,来决定是否重新渲染组件

    • **注意: **纯组件内部的对比是 shallow compare(浅层对比)

      • 对于引用类型来说:只比较对象的引用(地址)是否相同
      • 所以,state 或 props 中属性值为引用类型时,应该创建新数据,不要直接修改原数据
      javascript
      class Far extends PureComponent {
        state = {
          obj: {
            num: 0,
          },
        };
      
        getRandomIntInclusive(min, max) {
          min = Math.ceil(min);
          max = Math.floor(max);
          return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
        }
        handle = () => {
          // 错误的写法
          // 重新设置的obj和上一次的obj是同一个.
          // 组件不会重新渲染了
          // let num = this.getRandomIntInclusive(1, 3)
          // let obj = this.state.obj 或者 let {obj} = this.state
          // obj.num = num
      
          // 正确的写法:
          let num = this.getRandomIntInclusive(1, 3);
          // 创建一个新的对象
          let obj = { num };
          console.log(num);
          this.setState({
            obj,
          });
        };
      
        render() {
          console.log("父组件渲染了");
          return (
            <div>
              <h1 onClick={this.handle}>Far组件</h1>
              <p>{this.state.obj.num}</p>
              <Son num={this.state.obj.num}></Son>
            </div>
          );
        }
      }