React函数样式组件直接调用vs jsx - 其中是子节点?

时间:2017-05-12 05:09:53

标签: javascript reactjs react-jsx jsx

我试图了解自定义组件jsx样式的子节点在哪里?

const appDom = document.getElementById('app')

const Hey = () => <div><i>HEY</i><b>you</b></div>
const Hello = () => <div><h1>Hello</h1></div>

console.log('ola', Hey()['props'])
console.log('hola', <Hey />['props']) // Where is children?


ReactDOM.render(<div>{Hey()}<br/><Hey/></div>, appDom)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

1 个答案:

答案 0 :(得分:2)

要找到问题的答案,首先,我们需要了解将JSX转换为普通JavaScript时会发生什么。编译器只需用React.createElement方法重写整个JSX标记树。

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

在此转换为React.createElement

  • JSX标记将作为类型传递,
  • 标记的所有属性将组合成一个JavaScript对象并作为props和
  • 传递
  • 在递归应用React.createElement方法后,JSX标记之间的内容将作为子标记传递。

这个React.createElement返回一个React Element,它只是一个普通的对象。

所以你的Hey组件将以普通的JavaScript形式出现如下内容。

const Hey = () => React.createElement(
  "div",
  null,
  React.createElement(
    "i",
    null,
    "HEY"
  ),
  React.createElement(
    "b",
    null,
    "you"
  )
);

并且您的控制台日志行将是这样的。

console.log('ola', Hey()['props']);
console.log('hola', React.createElement(Hey, null)['props']);

现在,如果仔细查看这些日志行,第一行打印的是props div的反应元素,它有两个孩子;我反应元素和b反应元素。但是第二行打印了props的Hey反应元素,它没有任何孩子。所以它不会打印孩子因为它没有孩子。基本上,Hey()<Hey/>并不是一回事,即使它们呈现的内容没有区别。

为了更好地理解它,让我们尝试另外的控制台日志,如下所示,

console.log('hola', <Hey>abc</Hey>['props'])

转换为

console.log('hola', React.createElement(Hey, null, 'abc' )['props']);

这仍然会打印出Hey反应元素的props,但它会有一个儿童道具,这就是&#39; abc&#39;字符串。

希望这会回答你的问题。