ReactJS - cloneElement() 函数
React 是一个用于创建用户界面的著名 JavaScript 库。它包含许多功能,可帮助我们创建灵活且可维护的代码。CloneElement 就是其中一种工具,它允许我们基于前一个 React 元素创建新的 React 元素,同时修改其属性和子元素。那么让我们看看 cloneElement 是什么以及如何使用它。
什么是 cloneElement?
术语 cloneElement 是一种 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 和 Button
在此应用中,我们将首先从"react"库导入必要的模块。导入 cloneElement 是为了对基本 React 元素进行修改。现在我们将使用 JSX 创建一个基本 React 元素。此元素是一个带有文本内容的简单 <div>。定义 App 功能组件。在此组件内,我们将使用 cloneElement 创建 basicElement 的修改版本。修改涉及添加一个名为 newProp 的新 prop,其值为"添加的 prop 值"。
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"库导入必要的模块。同时导入 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 组件 − 它将产品标题呈现为一行。如果 isHighlighted 属性为真,则应用 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 是 React 中的一个有用函数,它通常被使用,并且可能会给我们的程序增加复杂性和问题。了解何时在 React 应用程序中使用 cloneElement 以及何时使用其他技术可以帮助我们编写更干净、更高效的代码。