0%

react-souce-1

  • jsx 不只是模板语法的一种,jsx 作为 react 框架的一大特色,与其运行机制有千丝万缕的联系
  • jsx 是 JavaScript 的一种语法扩展工具,和模板语法很接近,但是充分具备 js 的能力
  • 浏览器不会像对 js 一样直接支持,而是需要通过 Babel 转化
  • Babel 是一种 JavaScript 编译工具,能够将 ES2015 以上的版本转化为向后兼容的 js 语法,适配低版本浏览器,另外还可以转化 jsx、typescript…

jsx 会被编译为 React.createElement(), React.createElement() 将会返回一个 React Element 对象

1
2
3
4
<div className="App">
<h1 className="app__title">Hello World</h1>
<p className="app__desc">React and JSX</p>
</div>

转换后

1
2
3
4
5
6
7
8
9
10
"use strict";

/*#__PURE__*/
React.createElement("div", {
className: "App"
}, /*#__PURE__*/React.createElement("h1", {
className: "app__title"
}, "Hello World"), /*#__PURE__*/React.createElement("p", {
className: "app__desc"
}, "React and JSX"));

createElement()

React.createElement() 接收 3 个以上参数:

  • type: 要创建的 React 元素类型;可以是标签字符串如 “div”、”p”…;也可以是 React 组件类型(class组件或者函数组件);或者是React fragment类型
  • config: 写在标签上的属性的集合js对象格式,若标签上未添加任何属性则为 null
  • chidlren: 第三个及以后的参数为当前 React 节点的子节点;若是文本节点则为字符串类型;否则为新的 React.createElement 创建的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
export function createElement (type, config, children) {
let propName;
// 元素的属性 键值对 收集
const props = {}

// 将 config 中的属性 除 key | ref | __self | __source 外
// 添加到 props 中
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
// 第三个及之后的参数(子节点个数) 长度
const childrenLength = arguments.length - 2;
// 只有一个参数(节点)则为 文本节点
if (childrenLength === 1) {
// 直接给 props 的 children 属性
props.children = children;
} else if (childrenLength > 1) { // 表示有多个子节点
// 推入一个数组中再给 children
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
}

return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}

ReactElement()

React.createElement() 主要用于数据的格式化,形成 ReactElement() 所预期的格式并传入 ReactElement(),后者将 组装完成的 react element 对象返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// 一个常量,用来标识该对象是一个 ReactElement
$$typeof: REACT_ELEMENT_TYPE,
// 内置属性赋值,用于创建真实 dom 的相关信息
type: type,
key: key,
ref: ref,
props: props,
_owner: owner,
}
if (__DEV__) {
// 在开发环境下通过 Object.defineProperty
// 将_store、_self、_source 设置为不可枚举,提高element比较时的性能
}
return element;
}

对比

1
2
3
4
5
6
7
console.dir(React.createElement(
'h1',
{
id: 'HelloComponent'
},
'Hello World !'
));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
$$typeof: Symbol(react.element),
type: "h1",
key: null,
ref: null,
props: {
id: "HelloComponent",
children: "Hello World !",
__proto__: Object,
_owner: null,
},
_store: {
validated: false,
__proto__: Object,
},
_self: null,
_source: null,
__proto__: Object
}

ReactDOM.render()

ReactDOM.render(<App />, document.getElementById('root'))

1
2
3
4
5
6
7
8
ReactDOM.render(
// 需要渲染的元素 ReactElement
element,
// 挂载的容器(真实 DOM)
container,
// 可选回调,用于处理渲染结束后的逻辑
callback?
)
-------------本文结束感谢您的阅读-------------