JSX是一个 JavaScript 的语法扩展,在编译阶段被babel编译成为 React.createElement() 函数调用。
所以会在jsx文件中 引入React , import React from ‘react’;

  1. const element = (
  2. <h1 className="greeting">
  3. Hello, world!
  4. </h1>
  5. );
  1. const element = React.createElement(
  2. 'h1',
  3. {className: 'greeting'},
  4. 'Hello, world!'
  5. );

React DOM 在渲染所有输入内容之前,默认会进行转义。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击

JSX本质上就是一个JS对象,对象中包含了type、key、props、ref等属性
image.png

React.createElement

  1. export function createElement(type, config, children) {
  2. let propName;
  3. const props = {};
  4. let key = null;
  5. let ref = null;
  6. let self = null;
  7. let source = null;
  8. if (config != null) {
  9. // 将 config 处理后赋值给 props
  10. // ...省略
  11. }
  12. const childrenLength = arguments.length - 2;
  13. // 处理 children,会被赋值给props.children
  14. // ...省略
  15. // 处理 defaultProps
  16. // ...省略
  17. return ReactElement(
  18. type,
  19. key,
  20. ref,
  21. self,
  22. source,
  23. ReactCurrentOwner.current,
  24. props,
  25. );
  26. }
  27. const ReactElement = function(type, key, ref, self, source, owner, props) {
  28. const element = {
  29. // 标记这是个 React Element
  30. $$typeof: REACT_ELEMENT_TYPE,
  31. type: type,
  32. key: key,
  33. ref: ref,
  34. props: props,
  35. _owner: owner,
  36. };
  37. return element;
  38. };

可以看到,React.createElement最终会调用ReactElement方法返回一个包含组件数据的对象,该对象有个参数$$typeof: REACT_ELEMENT_TYPE标记了该对象是个React Element

JSX与Fiber

JSX是一种描述当前组件内容的数据结构,不包含组件schedulereconcilerender所需的相关信息。
如下信息就不包括在JSX中:

  • 组件在更新中的优先级
  • 组件的state
  • 组件被打上的用于Renderer标记

这些内容都包含在Fiber节点中。
所以,在组件mount时,Reconciler根据JSX描述的组件内容生成组件对应的Fiber节点
update时,ReconcilerJSXFiber节点保存的数据对比,生成组件对应的Fiber节点,并根据对比结果为Fiber节点打上标记