React.cloneElement是啥
React.cloneElement是React提供的一个API,用于在保留原有props的基础上,克隆一个React元素,并可选地修改新元素的props或children
React.cloneElement(
element, // 要克隆的React元素,封装组件,对象
[props], // 可选,新元素要修改的props
[...children] // 可选,新元素要替换的children,不光是content还有样式和element,type
)
简单举个例子
// 传参确定要修改的属性是color和children
function Button(props) {
return <button style={{ backgroundColor: props.color }}>{props.children}</button>
}
// 传入自定义元素,和要修改的属性
const newProps = { color: 'red' }
const newButton = React.cloneElement(
<Button>Hello World</Button>,
newProps,
<h1>我是新元素,带type</h1>
)
//用React.cloneElement,通过传入新的props修改原有组件的样式和children
const newButton = React.cloneElement(<Button>Hello World</Button>, newProps)
//用React.cloneElement,通过传入新的props修改原有组件的样式
-
children是指,若传入第三个参数,他会替代element元素及其content,若不传默认就是element元素中的内容
这个children返回的是对象(跟cloneElement的第三个参数有关)
-
没有第三个参数,children就是指第一个参数中测content
这个children返回的是值
-
如果第二个参数不传入,则获取不到props其他数据,只有默认children
这个children返回的是值
再举个例子
const NewEle = (props: any) => (
<div style={{...props.style}}>
这是自定义的元素{props.children}
</div>
)
const CloneEle = ({ dom = <div/>, ...rest }) => {
const styles = {
color: 'blue',
textAlign: 'left',
fontSize: '20px'
}
//要克隆的元素、要更改的属性值进行了封装, 样式和内容进行分开处理
return React.cloneElement(dom, {style:styles,...{dom.props},...rest})
}
// P元素和内容,会替代dom中的默认<div/>, 而封装的styles因为没有可以替代的也会被保留。
// 而最上面的NewEle子组件,可以把cloneElement里面三个参数的所有数据都获取
const renderEle = () => {
return (
<CloneEle dom={<NewEle style={{color: 'red', fontWeight: 'bold'}} />}>
<p>这是父组件元素</p>
</CloneEle>
)
}
const NewEle = (props: any) => {
console.log(props, 888999)
return <div style={{fontSize:'20px', textAlign: 'left', color: props.color || 'blue'}}>这是自定义的元素{props.children}</div>
}
const renderEle = () => {
const newProps = {color: 'red', fontWeight: 'bold'}
return React.cloneElement(<NewEle><p>这是父组件元素</p></NewEle>, newProps)
}
这样理解起来就没有那么困难, 但是第一种写法经过封装,也有它的优势 哪些场景可以用呢,组件扩展复用,但是这种用法可以直接被react组件自身已有的替代
//在子组件中cloumns的operate
<Button onClick={extendOperate.props.onClick} type="link"> {extendOperate.props.children}
</Button>
//父组件中
const extendOperateEle = (
<Button onClick={() => {console.log(333)}}>我是扩展的Button</Button>)
const cloneTable = React.cloneElement(
<NewTable
data={data}
/>,
{
extendOperateEle,
}
)
//组件本身可替代,
<NewTable
data={data}
>
<Button onClick={() => {console.log(333)}}>我是扩展的Button</Button>
</NewTable>
除了上面封装的元素,另外一种就是下面这种了比较有意义
<ModalButton>
<Button>我是子元素</Button>
</ModalButton>
const cloneEle = React.cloneElement(props.children, {onClick(){modalVisible = true}}
{cloneEle}
//用React.cloneElement,获取该元素的children--button,对button添加方法, 把方法放到组件内部
哪些场景可以用到呢,与弹窗类似的组件,抽屉,tab切换,等
使用React.cloneElement的优势在于:
- 可以避免重复编写类似的组件代码,提高代码复用率。例如,我们可以通过克隆一个Button组件,将其样式改变,然后得到一个新的PrimaryButton组件,而不需要再单独编写一个PrimaryButton组件。
- 可以方便地对已有组件进行扩展和修改,而无需修改原有组件代码。例如,我们可以通过克隆一个Button组件,将其添加一个新的props,用于处理点击事件,而不需要修改原有Button组件的代码。 使用React.cloneElement的劣势在于:
- React.cloneElement方法存在副作用,即会修改已有组件的props。如果不小心修改了原有组件的props,可能会导致组件功能出现问题。
- React.cloneElement方法只能针对已有组件进行修改,无法创建新的组件。如果需要创建新的组件,仍需要手动编写新的组件代码。