【问题标题】:Undocumented method of passing element children: as attributes instead of explicit children传递元素子项的未记录方法:作为属性而不是显式子项
【发布时间】:2017-10-17 22:42:43
【问题描述】:

我在一本书中遇到了一些示例 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 &lt;a {...props}&gt;{props.children}&lt;/a&gt;

后一种形式实际上是在同一本书中更早一些的方式,并且没有对新的更简洁的形式给出解释。 FWIW,这本书是 Stoyan Stefanov 的“React Up & Running”。在考虑提交建议以向本书添加解释之前,我将不胜感激。

Codepen:https://codepen.io/anon/pen/EmeOxW?editors=0010

【问题讨论】:

  • 简而言之,JSX内部&lt;AnyTag children={children} /&gt;等价于&lt;AnyTag&gt;{children}&lt;/AnyTag&gt;
  • 顺便说一下,&lt;a {...props}&gt;{props.children}&lt;/a&gt; 会通过两次children。这不会改变结果,也不会破坏某些东西……只是提醒一下。
  • @Chris:不,你的回答并没有真正回答我脑海中的问题,我可能没有正确表达。 :) 我已经知道它有效——我可以亲眼看到,而无需深入研究 React 代码。我想知道两件事:a) 作者是如何知道他们可以这样传递孩子的?我重新阅读了 React JSX 文档,对我来说根本不明显这是一种受支持的传递孩子的方式。 b) 它被认为是“惯用的”JSX 吗?我知道你似乎不这么认为——你是一位经验丰富的 React 开发人员吗? :) :)
  • @Chris:我的第二个例子是两次传递孩子,是的,我意识到 - 我很懒惰。这本书实际上做得很好,并展示了如何从 props 对象等中删除属性。
  • 再次感谢 Chris - 我会尽量避免这种语法,至少目前是这样。我会看看 React 文档的其余部分关于 props 的说法,然后考虑提交一个针对 React 文档的问题,并且还将提交一个(温和的)勘误表,以便考虑添加解释。但是,是的,我同意它应该起作用是有道理的。

标签: javascript reactjs ecmascript-6 jsx


【解决方案1】:

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


说明

那么发生了什么?需要仔细查看源代码以了解发生了什么:

ReactElement.js 的 react 库第 170 行:

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 对象中的每个值(即第二个函数参数!),我们使用propName 键将其传递给props。但是,请记住,您在 &lt;a&gt; 元素中解构了 props

换句话说,这个:

<a {...props} />

等于:

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

这意味着props 对象同时获得hrefchildren 属性,这就是您获得观察结果的原因。


总结

总而言之,就是这样:

<Foo children="Bar" />

等于:

<Foo>Bar</Foo>

意见:

话虽如此,我宁愿看到作者使用您建议的语法,而不是他/她的做法。人们希望教育材料更加清晰和准确。

【讨论】:

    猜你喜欢
    • 2018-12-18
    • 2018-05-28
    • 2013-11-16
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多