Skip to content
On this page

如何设计一个组件?常见的 React 组件设计模式 --- render-prop

render-prop

render-prop

渲染函数通过组件的 prop 传入组件内部,组件的使用者就可完全控制渲染的内容,可在组件内部传递相关参数。它是一种重用组件逻辑和状态的方式。

jsx
<Counter
  render={value => {
    return (
      <>
        <Decrement
          onDecrement={() => {
            setValue(value => value - 1)
          }}
        />
        <Label>计数器</Label>
        <Count count={value} max={10} />
        <Increment
          onIncrement={() => {
            setValue(value => value + 1)
          }}
        />
      </>
    )
  }}
  value={value}
/>

Counter 的实现:

jsx
import styled from 'styled-components'

function Counter({ render, value, children }) {
  console.log('Counter render')
  if (children) {
    return <StyledCounter>{children(value)}</StyledCounter>
  }
  return <StyledCounter>{render && render(value)}</StyledCounter>
}
const StyledCounter = styled.div`
  display: inline-flex;
  border: 1px solid #17a2b8;
  line-height: 1.5;
  border-radius: 0.25rem;
  overflow: hidden;
`
export { Counter }

children 是特殊的 prop,可将一个渲染函数当成 children 传入。

jsx
<Counter value={value1}>
  {value => {
    return (
      <>
        <Decrement
          onDecrement={() => {
            setValue1(value => value - 1)
          }}
        />
        <Increment
          onIncrement={() => {
            setValue1(value => value + 1)
          }}
        />
        <Label>计数器</Label>
        <Count count={value} max={10} />
      </>
    )
  }}
</Counter>

renderProp vs renderChildren

renderProp 可自由定义 prop 的名字,renderChildren 不能改名字。

renderProp 可读性不及 renderChildren, renderChildren 可清楚组件的开始和结束。

renderProp 还能再传递子组件,renderChildren 不能再传递子组件,renderProp 更加灵活。

关于 renderProp 的疑问

renderProp vs renderChildren 该用哪个?

renderProp

理由:renderProp 更加灵活,可重命名,好的命名极为重要。

将 renderProp 提取成函数,可解决可读性问题。

什么情况从组件内部给 renderProp 传递参数?从内部传递参数有什么好处吗?不传递参数,也能实现相同的功能。

目前 react 还没遇到必需从内部传递参数的情况。 vue 需要从内部传递参数,使用起来才方便。

vue 中如何实现 renderProp?

把 h 函数作为普通函数的第一个参数,那么这个函数被当成渲染函数,可返回 jsx,再把该函数通过 props 传递给组件,组件的 setup 或者 render 返回这个函数的调用,即可实现在数据里写 jsx,提高组件的可维护性和扩展性。

具体看如何使用 render 改善组件

参考

Use a Render Prop!

Function as Child Components

When to NOT use Render Props

Released under the MIT License.