React三种通过属性传递组件本身的方法

直接传递 JSX 创建好的元素

把要传递的组件作为 JSX 元素写在属性值里,然后在接收的组件里用 {this.props.xxx} 来渲染。这种方法的优点是直观和灵活,缺点是可能造成不必要的重复渲染。

// 父组件
function Profile() {
  return (
    <div>
      <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} />
      <Avatar size={80} person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }} />
      <Avatar size={50} person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} />
    </div>
  );
}

// 子组件
function Avatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

直接传递 JSX 创建好的元素的方法会造成不必要的渲染,是因为每次父组件重新渲染时,都会创建一个新的 JSX 元素,即使它的内容没有变化。这样会导致 React 认为子组件的属性发生了变化,从而触发子组件的重新渲染。
在上述代码中,每次 Profile 重新渲染时,都会创建一个新的 JSX 元素,每次 person 属性变化时,都会重新渲染 Avatar。

传递组件本身

把要传递的组件作为一个变量或常量,然后把它赋值给属性。这种方法的优点是可以避免重复渲染,缺点是需要额外定义一个变量或常量。

// 父组件
import { DownloadOutlined } from '@ant-design/icons';

function Profile() {
  return (
    <div>
      <Button icon={<DownloadOutlined />} />
    </div>
  );
}

// 子组件
function Button({ icon }) {
  return (
    <button className="button">
      {icon}
    </button>
  );
}

传递返回 JSX 创建好的元素的函数

把要传递的组件封装成一个函数,然后把函数赋值给属性。

// 父组件
function Profile() {
  return (
    <div>
      <Button renderIcon={() => <DownloadOutlined />} />
    </div>
  );
}

// 子组件
function Button({ renderIcon }) {
  return (
    <button className="button">
      {renderIcon()}
    </button>
  );
}

这种方法的优点是可以实现动态渲染和传递参数,缺点是可能造成性能损失。是因为每次父组件重新渲染时,都会调用一次函数,即使函数的返回值没有变化。这样会导致 React 认为子组件的属性发生了变化,从而触发子组件的重新渲染。
在上述代码中,每次 Profile 重新渲染时,都会调用一次 renderIcon 函数;每次 renderIcon 属性变化时,都会重新渲染 Button。
为了避免这种情况,可以使用 useCallback 钩子来缓存函数的引用。或者使用 React.memo 来优化子组件的渲染性能。

使用 useCallback 钩子来缓存函数的引用
// 父组件
import React, { useCallback } from 'react';

function Profile() {
  // \uD83D\uDC47️ 使用 useCallback 钩子来缓存函数的引用,避免每次重新渲染时都创建一个新的函数
  const renderIcon = useCallback(() => <DownloadOutlined />, []);
  return (
    <div>
      <Button renderIcon={renderIcon} />
    </div>
  );
}

// 子组件
function Button({ renderIcon }) {
  return (
    <button className="button">
      {renderIcon()}
    </button>
  );
}
使用 React.memo 来优化子组件的渲染性能
// 父组件
function Profile() {
  return (
    <div>
      <Button renderIcon={() => <DownloadOutlined />} />
    </div>
  );
}

// 子组件
// \uD83D\uDC47️ 使用 React.memo 来包裹子组件,避免属性相同的情况下重新渲染
const Button = React.memo(function Button({ renderIcon }) {
  return (
    <button className="button">
      {renderIcon()}
    </button>
  );
});

你可能感兴趣的:(前端,React,前端)