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,则克隆的元素将保留所有原始属性。
  • ...children - 有零个或多个子节点。它们可以是任何 React 节点,例如元素、字符串或数字。如果我们不传递任何子项,则将使用原始子项。

返回值

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

  • type − 与 element.type 相同。
  • props - element.props 和覆盖 props 的组合。
  • ref - 原始 ref,除非被 props.ref 覆盖。
  • key - 原始键,除非被props.key覆盖。

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

例子

示例 - 添加新的道具和按钮

在这个应用程序中,我们将首先从“react”库中导入必要的模块。cloneElement 用于对基本 React 元素进行修改。现在我们将使用 JSX 创建一个基本的 React 元素。此元素是一个简单的 <div>,包含文本内容。定义 App 功能组件。在此组件中,我们将使用 cloneElement 来创建 basicElement 的修改版本。修改涉及添加一个名为 newProp 的新道具,其值为“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;

输出

基本 React 元素

当我们在 React 应用程序中使用此组件时,它将渲染修改后的元素以及一个按钮。单击该按钮将显示一条警报,提示“按钮已点击!

示例 - 添加项目列表

在这个例子中,我们将首先从'react'库中导入必要的模块。并且还导入了 cloneElement 以对基本 React 元素进行修改。现在我们将有一个使用 JSX 的基本 React 元素。这个元素是一个简单的 <div>,文本内容是“这是一个基本的 React 元素”。然后定义 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;

输出

项目清单

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

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

在这个应用程序中,我们将创建一个简单的 React 应用程序,该应用程序使用 cloneElement 来突出显示项目列表中的特定项目。该应用由两个组件组成:List 组件和 Row 组件,其父 App 组件显示产品列表。

  • List 组件 - 它接收子组件的列表。保持 selectedIndex 状态以跟踪当前突出显示的项。使用 Children.map 遍历子项,并使用 cloneElement 根据 selectedIndex 修改 isHighlighted 属性。
  • Row 组件 - 它将产品标题呈现为一行。并应用一个 CSS 类来高亮显示 isHighlighted 属性是否为 true。
  • 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>
	 	);
}

输出

clone元素

总结

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