为什么组件只能 return ReactJS 中的一个节点? (有根本原因吗?)

Why can components only return one node in ReactJS? (Is there a fundamental reason?)

来自文档:

Maximum Number of JSX Root Nodes

Currently, in a component's render, you can only return one node; if you have, say, a list of divs to return, you must wrap your components within a div, span or any other component.

Don't forget that JSX compiles into regular js; returning two functions doesn't really make syntactic sense. Likewise, don't put more than one child in a ternary.

上面的解释说 "currently," 这表明一个组件可能 return 一个函数会导致两个节点而不是一个节点。这只是一个技术限制,还是融入了理念?

我是如何想到这个问题的:我正处于一种情况,我正在尝试使用 React 呈现 Bootstrap 菜单,并且 Bootstrap 使用子选择器,而不是后代选择器,这很有道理。


旁白: 我是如何解决我的特定问题的:

我最感兴趣的是 React 的架构,但如果你好奇这就是我的情况。

目前在Bootstrap你可以做一个下拉菜单:

<li role="presentation" class="dropdown pull-right">
    <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="true"> Menu <span class="caret"></span> </a>
    <div id="macroMenu" class="react-component">
        <ul class="macroInsertion dropdown-menu" role="menu">
            <li>
                <form class="navbar-form navbar-left" role="search">
                    <div class="form-group">
                        <input type="text" class="form-control search-filter" placeholder="Search" />
                    </div>
                </form>
            </li>
            <li>
                <a href="#">Menu 1</a>
            </li>
            <li>
                <a href="#">Menu 2</a>
            </li>
            <li class="divider"></li>
            <li>
                <a href="#">Menu 3</a>
            </li>
        </ul>
    </div>
</li>

默认 Bootstrap 样式表具有选择器,例如 .pull-right > .dropdown-menu 和 .open > .dropdown-menu,如果您在容器和容器之间插入单个元素,它们将不起作用包含。这是有道理的,因为它可能更快并且 Bootstrap 有时可能会处理双嵌套选择器,但它破坏了我们的系统以在中间有 .react-component。

在我的例子中,我手动找出了 .react-component 的问题并制作了新的样式来解决缺失的行为。

这是目前的技术限制。然而,有一些(随意的)谈论允许这样做:

var Foo = React.createClass({
  render(){
    return [<Bar />, <Baz />];
  }
});

var Quux = React.createClass({
  render(){
    return <div><span /><Foo /></div>;
  }
});

<Quux /> 将导致此结构:

<div>
    <span />
    <Bar />
    <Baz />
</div>

这对于处理 HTML(表格、列表、标题)中的一些僵化问题很有用,对于兄弟姐妹重要的地方(例如 display: inline-block)或您无法控制的地方的样式也很有用使用样式和直接 child (>) 或兄弟选择器(~+)。

如果您 运行 遇到其中一种情况,您很可能只是在实现渲染,因此使用实用函数而不是组件将是一个很好的解决方法。

var Foo = function(props){
    return [<Bar />, <Baz />];
}

var Quux = React.createClass({
  render(){
    return <div>{flatten( <span />, Foo({}) )}</div>;
  }
});


// usually you get this from underscore or similar
var flatten = function(){ return Array.prototype.reduce.call(arguments, function(acc, x){ return acc.concat(x) }, []) };