传递元素子项的未记录方法:作为属性而不是显式子项

Undocumented method of passing element children: as attributes instead of explicit children

我在一本书中遇到了一些示例 JSX 代码,这让我感到惊讶 - 它包含一个单一(非封闭)形式的锚标记。我已经简化了代码:

function CustomAnchor(props) {
    return <a {...props}/>;
};

ReactDOM.render(
  <CustomAnchor href="http://reactjs.com">A link</CustomAnchor>,
  document.getElementById('container')
);

该代码有效,但我无法找到任何描述这种在 JSX 中描述锚标记的方式的文档。我预计必须使用开始和结束 A 标签,包含 props.children - 即 - 像这样的东西:

return <a {...props}>{props.children}</a>

实际上,后一种形式在同一本书的较早部分是如何完成的,并且没有对新的更简洁的形式进行解释。 FWIW,这本书是 "React Up & Running",作者是 Stoyan Stefanov。在我考虑提交为本书添加解释的建议之前,我会很感激这里的一些帮助。

代码笔:https://codepen.io/anon/pen/EmeOxW?editors=0010

JSX 和 React.createElement()

如果你查看 Babel Compiler,你会看到这个 JSX:

function CustomAnchor() {
  return <a {...props} />;
}

编译成:

function CustomAnchor() {
  return React.createElement("a", props);
}

createElement() 函数具有以下语法,根据 official documentation:

createElement():

React.createElement(
  type,
  [props],
  [...children]
)

所以你的观察是有道理的!有人会认为,既然省略了第三个参数,那么就不应该有任何 children.


说明

所以这是怎么回事?需要仔细查看源代码才能了解发生了什么:

在react库第170行的ReactElement.js中:

ReactElement.createElement = function (type, config, children) {
  var propName;

  // Reserved names are extracted
  var props = {};

  ........

  for (propName in config) {
    if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
      props[propName] = config[propName];
    }
  }
}

对于 config 对象中的每个值(即 第二个函数参数 !),我们将其传递给 propspropName 钥匙。但是,请记住,您在 <a> 元素.

中解构了 props

换句话说,这个:

<a {...props} />

等于:

<a href="http://reactjs.com" children="A link" />

这意味着 props 对象同时获得 hrefchildren 属性,这就是为什么您会得到观察到的结果。


总结

总而言之,这:

<Foo children="Bar" />

等于:

<Foo>Bar</Foo>

意见:

也就是说,我宁愿看到作者使用您建议的语法,而不是 he/she 的做法。人们希望教育 material 更加清晰和准确。