ReactJs - 如何在组件中使用多个子元素

12

首先,我声明一下,我对ReactJs非常陌生,并且可能试图解决一些非常基础的问题。

我有一段带有自定义HTML代码的代码:

示例组件

const Sample = ({ title, children }) => {
    return (
          <div class="panel">
              <div class="title">
                 {title}
              </div>
              <div class="body">
                 {children}
              </div>
           </div>    
     );
};

附带问题 - 上面的内容应该叫什么?是一个“片段”吗?它似乎不是一个“组件”,但我也在学习React的命名规范

使用组件

export default class ExampleComponent extends Component {
    render() {
        return <div class="page-body">
            <div class="row">
                <h1> Page 1 </h1>
                <Sample title={<h1>Some title!</h1>}>
                   <p>This is my sample body!</p>
                </Sample>
            </div>
        </div>
    }
}

你可以看到,“Sample”元素的内容会自动作为“children”属性,但要设置标题,我必须显式地设置“title”属性。我理想的做法类似于以下方式:
export default class ExampleComponent extends Component {
    render() {
        return <div class="page-body">
            <div class="row">
                <h1> Page 1 </h1>
                <Sample title="Some title!">
                   <Sample.Title>
                       <h1>This is my new way to do a title</h1>
                   </Sample.Title>
                   <Sample.Body>
                       <p>This is my sample body!</p>
                   </Sample.Body>
                </Sample>
            </div>
        </div>
    }
}

我以前使用过其他人创建的组件来实现这种方法,但现在想自己做,发现很难找到一个简单的示例来实现它。
非常感谢您提供任何指导!

1
以上是一个组件。片段是<>/* 内容 */</> - Kobe
1
在您期望的输出中,您确定要通过 title="Some Title!" 吗?这似乎违背了以下代码的目的 ;) - Kobe
3个回答

19

我认为你所需要的是JSX命名空间。你可以实例化Sample,然后将更多组件作为Sample的属性添加(把它视为一个对象)。

import React from "react"

const Sample = ({ children }) => (
  <div className="panel">
      {children}
  </div>    
)


Sample.Title = (props) => <div className="title">{props.children}</div>
Sample.Body = (props) => <div className="body">{props.children}</div>

export default Sample

注意:React使用className而不是class,因为我们在使用JSX。


这对我的情况非常完美!谢谢大家的建议!!:-D - Rob McCabe
1
@RobMcCabe 不用担心。如果你需要更多关于React的帮助或者有什么不理解的地方,随时问我就好了。 - Kobe
100个赞给你的回答。 - Rahul

13

Children 工具套件可以对您的场景有所帮助。

import { Children } from 'react'

const Sample = ({ title, children }) => {
  let _body, _title

  Children.forEach(children, child => {
    if (child.type === SampleTitle) {
      return _title = child
    }

    if (child.type === SampleBody) {
      return _body = child
    }
  })

  if (!_title) _title = <div className='title'>{title}</div>
  if (!_body) _body = <div className='title'>{children}</div>

  return (
    <div className='panel'>
      {_title}
      {_body}
    </div>
  )
}

const SampleTitle = ({ children }) => <div className='title'>{children}</div>
const SampleBody = ({ children }) => <div className='body'>{children}</div>

Sampe.Title = SampleTitle
Sample.Body = SampleBody

现在您可以以多种方式使用示例:

<Sample title="my title">
  <div>my body</div>
</Sample>

<Sample title="my title">
  <Sample.Body>my body</Sample.Body>
</Sample>

<Sample title="my fallback title">
  <Sample.Title>my overriding title</Sample.Title>
  <Sample.Body>my body</Sample.Body>
</Sample>


3
在这种情况下,您只需将相关容器提取到它们自己的组件中即可:
const Sample = ({children }) => (
    <div className="panel">{children}</div>    
);

const Title = ({children}) => (
    <div className="title">{children}</div>
);

const Body = ({children}) => (
    <div className="body">{children}</div>
);

Sample.Title = Title;
Sample.Body = Body;

请注意,用于CSS类的正确属性是className

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接