ReactJS - cloneElement() 函数



React 是一个著名的 JavaScript 库,用于创建用户界面。它包含许多特性,可以帮助我们创建灵活且易于维护的代码。cloneElement 就是这些工具之一,它允许我们基于之前的 React 元素创建一个新的 React 元素,同时修改其属性和子元素。因此,让我们了解一下 cloneElement 是什么以及如何使用它。

什么是 cloneElement?

cloneElement 是一个 React 方法,允许我们使用现有的 React 元素创建一个新的 React 元素。当我们想要更新元素的属性或向其添加子元素而无需更改原始元素时,这非常有用。

语法

const clonedElement = cloneElement(elem, props, ...children)

参数

  • elem − 这是一个有效的 React 元素,例如 JSX 节点或另一个 cloneElement 调用的结果。

  • props − 它是一个对象或 null,允许我们覆盖元素的属性。如果我们传递 null,则克隆的元素保留所有原始 props。

  • ...children − 有零个或多个子节点。它们可以是任何 React 节点,例如元素、字符串或数字。如果我们不传递任何子节点,则将使用原始子节点。

返回值

cloneElement 函数返回一个具有以下属性的 React 元素对象:

  • type − 与 element.type 相同。

  • props − element.props 和覆盖的 props 的组合。

  • ref − 原始 ref,除非被 props.ref 覆盖。

  • key − 原始 key,除非被 props.key 覆盖。

cloneElement 最常见的用途是覆盖元素的属性。如果我们有一个现有的元素并想要更新特定属性,我们可以简单地使用 cloneElement 来实现。

示例

示例 - 添加一个新的 Prop 和按钮

在这个应用中,我们将首先从 'react' 库导入必要的模块。导入 cloneElement 以对基本的 React 元素进行修改。现在,我们将使用 JSX 创建一个基本的 React 元素。此元素是一个简单的 <div>,包含文本内容。定义 App 函数式组件。在这个组件中,我们将使用 cloneElement 创建 basicElement 的修改版本。修改包括添加一个名为 newProp 的新 prop,其值为 'Added prop value'。

import React, { cloneElement } from 'react';

const basicElement = <div>This is a basic React element.</div>;
const App = () => {
   const modifiedElement = cloneElement(basicElement, { newProp: 'Added prop value' });
   return (
   <div>
   {modifiedElement}
   <button onClick={() => alert('Button clicked!')}>Click me</button>
   </div>
   );
};

export default App;

输出

basic react element

当我们在 React 应用中使用此组件时,它将呈现修改后的元素以及一个按钮。单击按钮将显示一条警报,内容为“Button clicked!”。

示例 - 添加项目列表

在这个示例中,我们将首先从 'react' 库导入必要的模块。同样,导入 cloneElement 以对基本的 React 元素进行修改。现在,我们将使用 JSX 创建一个基本的 React 元素。此元素是一个简单的 <div>,包含文本内容“This is a basic React element.”。然后定义 App 函数式组件。在这个组件中,我们将定义一个项目数组。我们将使用 cloneElement 创建 basicElement 的修改版本。修改包括添加一个段落 (<p>) 和一个无序列表 (<ul>),该列表包含通过遍历 items 数组生成的列表项。

import React, { cloneElement } from 'react';

const basicElement = <div>This is a basic React element.</div>;
const App = () => {
   const items = ['Item 1', 'Item 2', 'Item 3'];
   const modifiedElement = cloneElement(basicElement, null,
   <>
      <p>List of Items:</p>
      <ul>
         {items.map((item, index) => (
            <li key={index}>{item}</li>
         ))}
      </ul>
   </>
   );
   return <div>{modifiedElement}</div>;
};

export default App;

输出

list of items

当我们在 React 应用中使用此组件时,它将呈现修改后的元素,显示一个段落和一个无序项目列表。

示例 - 让我们创建一个使用 cloneElement 的应用程序

在这个应用中,我们将创建一个简单的 React 应用,它使用 cloneElement 来突出显示项目列表中的特定项目。该应用包含两个组件:List 组件和 Row 组件,以及一个父级 App 组件,用于显示产品列表。

  • List 组件 - 它接收一个子组件列表。维护 selectedIndex 状态以跟踪当前突出显示的项目。使用 Children.map 迭代子项,并使用 cloneElement 根据 selectedIndex 修改 isHighlighted prop。

  • Row 组件 - 它将产品标题渲染为一行。如果 isHighlighted prop 为 true,则应用 CSS 类进行突出显示。

  • data.js 模块 - 它定义了一个产品对象的数组。

  • App.js - 在这个文件中,我们将导入 List 和 Row 组件以及产品数据。并使用 List 组件呈现产品列表。

List.js

import { Children, cloneElement, useState } from 'react';

export default function List({ children }) {
   const [selectedIndex, setSelectedIndex] = useState(0);
   
   return (
   <div className="List">
      {Children.map(children, (child, index) =>
         cloneElement(child, {
            isHighlighted: index === selectedIndex,
         })
      )}
      <hr />
      <button
         onClick={() => {
            setSelectedIndex((i) => (i + 1) % Children.count(children));
         }}
      >
         Next
      </button>
   </div>
   );
}

Row.js

export default function Row({ title, isHighlighted }) {
   return (
      <div className={['Row', isHighlighted ? 'RowHighlighted' : ''].join(' ')}>
         {title}
      </div>
   );
}

Data.js

export const products = [
   { title: 'Laptop', id: 1 },
   { title: 'Smartphone', id: 2 },
   { title: 'Headphones', id: 3 },
   { title: 'Tablet', id: 4 },
];

App.js

import List from "./List.js";
import Row from "./Row.js";
import { products } from "./data.js";

export default function App() {
   return (
      <List>
         {products.map((product) => (
            <Row key={product.id} title={product.title} />
         ))}
      </List>
   );
}

输出

cloneElement

总结

因此,cloneElement 是 React 中一个有用的函数,它通常被使用,但也可能会给我们的程序增加复杂性和问题。了解何时使用 cloneElement 以及何时在我们的 React 应用中使用其他技术,可以帮助我们编写更简洁、更高效的代码。

reactjs_reference_api.htm
广告