0%

React中的renderProps

回想一下,我们在react中,父组件给子组件传递某些东西(值、组件)的时候,是不是可以使用 propschildren 这2个来帮助我们。

概念

props通常是我们定义在标签身上的东西,我们一般称之为标签属性, 例如下面

<div title="这是标签属性,也是props"></div>

而children则是值react中的 props.children ,这个东西的作用是,存放标签体的内容,如何来理解呢?看下面

<!-- Parent是我们随便定义的一个组件 -->
<Parent>
这里是标签体的内容
</Parent>

由此我们知道,只要它只一个组件,组件的开始标签和结束标签之间的东西,就是这个组件的标签体内容

就以上面的这个例子,我们的Parent组件如何获取标签体的内容呢,自然是借助 props.children

function Parent(props) {
console.log(props.children)
return <h1>这是Parent组件,{props.children}</h1>
}

区别

  • props

通过往标签身上添加各种属性,以达到将某个值传递给子组件的方式

  • children

通过往标签体内添加 结构 ,以达到将某个 HTML 结构传递给子组件的方式

由此我们也看出来了,props可以传递普通值,函数,HTML结构等等,而children只能传递HTML结构


思考

这里我们引申出一个问题,看下面的代码

function Parent() {
return (
<div>
<h1>这是父组件Parent</h1>
<Child />
</div>
);
}

function Child() {
let name = '靓仔';

return (
<div>
<h2>这是子组件Child</h2>
<Grandson />
</div>
);
}

function Grandson() {
return (
<div>
<h3>这是孙组件Grandson</h3>
</div>
);
}

export default Parent;

上面我们定义了三个组件, 分别是父组件 Parent 、子组件 Child、孙组件 Grandson,我们的子组件里定义了一个变量 name

现在提一个需求,假如我想把子组件的name属性传递给孙组件,那么我应该怎么传?

聪明的人大概已经想到了,使用 props 传值

function Child() {
let name = '靓仔';

return (
<div>
<h2>这是子组件Child</h2>
<Grandson name={name}/>
</div>
);
}

function Grandson(props) {
return (
<div>
<h3>这是孙组件Grandson,父组件的name={props.name}</h3>
</div>
);
}

到这里,大家可能心里会想,这不挺简单的吗?

是吗?那我们来对代码结构进行一个改造

function Parent() {
return (
<div>
<h1>这是父组件Parent</h1>
<Child>
<Grandson />
</Child>
</div>
);
}

function Child(props) {
let name = '靓仔';

return (
<div>
<h2>这是子组件Child</h2>
{props.children}
</div>
);
}

function Grandson() {
return (
<div>
<h3>这是孙组件Grandson</h3>
</div>
);
}

export default Parent;

看上面的代码,我还是那个需求,将子组件的name传递给孙组件,这个时候你该怎么传?

在这个代码结构中,子组件没办法使用 props 进行传值

仔细思考几分钟,想到解决方案了吗?


renderProps

为了解决上面提到的问题,我们可以借助 render props,让我们来对代码进行一个改造

function Parent() {
return (
<div>
<h1>这是父组件Parent</h1>
<Child render={(name) => <Grandson name={name}/>} />
</div>
);
}

function Child(props) {
let name = '靓仔';

return (
<div>
<h2>这是子组件Child</h2>
{props.render(name)}
</div>
);
}

function Grandson(props) {
return (
<div>
<h3>这是孙组件Grandson,父组件的name={props.name}</h3>
</div>
);
}

export default Parent;

这样,问题就解决了~


解释

  • 什么是 render props

props就是写在标签身上的某个属性,属性值可以是普通值,也可以是函数,如果是函数,且这个函数的返回值是一个组件,我们就可以称之为是 render props

也就是说,你传递了一个函数,这个函数返回一个组件,然后你在子组件里调用了这个函数,让它返回的组件渲染到了页面上,那么这个函数就是一个渲染属性(render props)。

更直白的解释:你的这个props起到了渲染一个组件的作用。


  • <Child render={}> 这里的 render 属性是固定名字吗

它不是一个固定名字,你可以是render,也可以是其他任意的名字,例如我下面的 fn

<Child fn={(name) => <Grandson name={name}/>} />

  • <Parent> <Child/> </Parent> 是不是可以理解为 Vue里Solt的写法?

是的,可以这么理解,跟Vuejs里的插槽用法类似。


  • 为什么用 render props

就像我们上面的思考题,子组件要传递name属性给孙组件,如果你用 props.children 的方式你做不到!

在实际项目开发中,可能某些情况下你也会碰到类似这种问题。


  • 我可以子组件传给父组件,然后父组件再传给孙组件吗

可以,但是没必要,有更简单的为什么不用呢?如果是为了装逼当我没说


  • 给我说说上面代码的流程是怎样的
  1. 父组件给子组件传递了render这个函数,这个函数会返回一个孙组件,并且这个函数接受一个形参
  2. 子组件在内部调用了这个render函数,并传递了自己身上的name属性
  3. render函数被调用,接收到子组件传递的name,随后render将其以props的方式添加到孙组件标签身上
  4. 孙组件通过props.name接收到render函数添加在其身上的name属性
-------------本文结束    感谢阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!