react之React.cloneElement()

2020-07-23  本文已影响0人  雨落倾城夏微凉_e861

react提供的这个方法克隆组件的方法,可能我们在平常的开发中用的很少,主要可能是我们并不知道或者并不了解这个方法。因为我在之前react的children文章中用到过,所以我就进行了一系列的测试,发现真的非常的好用。我们同样使用一些小的demo来介绍他的功能。

React.cloneElement()接收三个参数第一个参数接收一个ReactElement,可以是真实的dom结构也可以是自定义的。第二个参数返回旧元素的props、key、ref。可以添加新的props,第三个是props.children,不指定默认展示我们调用时添加的子元素。如果指定会覆盖我们调用克隆组件时里面包含的元素。接下来我们开始测试

function CloneDemo(props){
  return React.cloneElement(<div/>,props,<p>这是一个克隆的元素</p>)
}
export default CloneDemo;
1.png 2.png

我先写了一个最简单的demo,克隆的元素div和给他添加的子元素p都正常展示了。接着测试他的功能,接着上面的例子

function CloneDemo(props){
  return React.cloneElement(<div/>,props,<p>这是参数传入的元素</p>)
}
function ContainerBox(){
  return <CloneDemo><h1>这是在父组件添加的元素</h1></CloneDemo>
}
export default ContainerBox;

我对代码进行了调整,增加了一个ContainerBox组件,并调用了克隆的元素,还给他添加了子元素,查看效果:


3.png

发现传入的参数元素覆盖了从父组件传入的元素,导致h1标签并没有被渲染。因为平常开发我们写公共组件可能从父组件传入的比较多,所以下面的例子都不传入第三个参数。

上面是直接渲染了一个div显然这样的写法很不友好,可能我们想渲染一个p元素,一个a元素甚至是一个自定义的,上面的写法显然已经不支持了,下面进行修改:

function CloneDemo({dom=<div/>,...props}){
  return React.cloneElement(dom,{...props})
}
function ContainerBox(){
  return <CloneDemo dom={<p></p>}><h1>这是在父组件添加的元素</h1></CloneDemo>
}
export default ContainerBox;

给克隆组件传入了一个dom,dom接收一个ReactElement,还给他赋予了一个默认值,如果没传入渲染div即可,我先给dom传入了一个p元素查看页面元素:


4.png

传入的p元素正常显示出来了。下来测试自定义的ReactElement看是否正常渲染

const Exam = (props) => <div>这是一个自定义的ReactElement元素{props.children}</div>
function CloneDemo({dom=<div/>,...rest}){
  return React.cloneElement(dom,{...rest})
}
function ContainerBox(){
  return <CloneDemo dom={<Exam style={{color: "red",textAlign: "center"}} />}><h1>这是在父组件添加的元素</h1></CloneDemo>
}
export default ContainerBox;

我创建了一个Exam组件,并将他传给克隆组件,我们还给他加上了样式查看效果:


5.png

可以正常显示但是发现样式并没有生效,接下来处理样式,主要需要两部分的样式,一部分是克隆的时候直接给的样式,一个是传入的组件的样式,处理原则是如果样式冲突,采用传入的样式。

const Exam = (props) => {
  return <div style={{...props.styles,...props.style}}>这是一个自定义的ReactElement元素{props.children}</div>
}
function CloneDemo({dom=<div/>, ...rest }){
  const styles = {
    color: "blue",
    minWidth: "1200px",
    margin: "100px auto",
    textAlign: "left"
  }
  return React.cloneElement(dom,{styles, ...rest})
}
function ContainerBox(){
  return <CloneDemo dom={<Exam style={{color: "red",textAlign: "center"}}  />}><h1>这是在父组件添加的元素</h1></CloneDemo>
}
export default ContainerBox;

我将CloneDemo中定义的styles,已经传入Exam组件时给他定义的样式都加到了Exam组件身上


6.png

继续优化克隆组件

const Exam = (props) => {
  return <div style={{...props.style}}>这是一个自定义的ReactElement元素{props.children}</div>
}
function CloneDemo({dom=<div/>, ...rest }){
  const styles = {
    color: "blue",
    minWidth: "1200px",
    margin: "100px auto",
    textAlign: "left"
  }
  return React.cloneElement(dom,{
    style: Object.assign({}, styles, dom.props.style), //将传入的样式放到最后提高他的优先级
    ...rest
  })
}
function ContainerBox(){
  return <CloneDemo dom={<Exam style={{color: "red",textAlign: "center"}}  />}><h1>这是在父组件添加的元素</h1></CloneDemo>
}
export default ContainerBox;

这样在Exam组件中只需要传入一个props.style样式就可以了。

上一篇 下一篇

猜你喜欢

热点阅读