一、react如何将代码显示到页面上
每当我们新建react项目时,项目创建成功后,运行npm start后会出现如下界面:
可以观察到时app.js中对该页面进行的设计,代码如下:
观察index.js发现最终代码是在这里执行的:
React将代码显示出来主要有两个步骤:
- JSX转化为Element
- Element转化为Dom
(1)JSX生成Element
1. JSX语法
可以看到第一个张图片中的render函数中return了一段html片段,这段片段就是JSX语法
定义:JSX 即Javascript XML,它是对JavaScript 语法扩展。React 使用 JSX 来替代常规的 JavaScript。你也可以认为JSX其实就是JavaScript。当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析。
优点:
执行速度更快,因为它在编译为JavaScript代码后进行了优化
2. 使用babel对JSX语法进行转换
return (
<div className="cn">
<Header> Hello, This is React </Header>
<div>Start to learn right now!</div>
Right Reserve.
</div>
)
通过babel编译成React.createElement的表达式。
return (
React.createElement(
'div',
{ className: 'cn' },
React.createElement(
Header,
null,
'Hello, This is React'
),
React.createElement(
'div',
null,
'Start to learn right now!'
),
'Right Reserve'
)
)
当render函数被调用时,会执行React.createElement的表达式,返回Element元素
3. 创建虚拟Dom
调用React.createElement方法时,React 把真实的 DOM 树转换成 Javascript 对象树,会创建虚拟Dom树,也就是 Virtual Dom。
每次数据更新后,重新计算 Virtual Dom ,并和上一次生成的 virtual dom 做对比,对发生变化的部分做批量更新。
而 React 是通过创建与更新虚拟元素 Virtual Element 来管理整个Virtual Dom 的。
虚拟元素可以理解为真实元素的对应,它的构建与更新都是在内存中完成的,并不会真正渲染到 dom 中去。
虚拟dom 实际上是对实际Dom的一个抽象,是一个js对象。
react所有的表层操作实际上是在操作Virtual dom。
(2)Element生成Dom
上一步通过JSX获得了虚拟Dom树,现在需要将虚拟Dom转化为真实的Dom,可以看到第二张图里的ReactDOM.render 方法。
这时可以利用 ReactDOM.render 方法,传入一个 reactElement 和一个 作为容器的 DOM 节点。
而这个方法查看到源码可以看见是调用了一个instantiateReactComponent函数,这个函数 创建了一个ReactComponent 的实例并返回,也可以看到 ReactDOM.render 最后返回的也是这个实例。
代码如下:
function instantiateReactComponent(node) {
var instance;
if (node === null || node === false) {
instance = new ReactEmptyComponent(instantiateReactComponent);----------(1)
} else if (typeof node === 'object') {
var element = node;
'
如果 type的类型是string 则说明它是 普通的HTML标签,那么直接按照普通的方式生成 DOM
而如果不是string的话,比如是
ƒ () ƒ App(props)之类的,则说明他们是 自定义的组件。
则要另行处理。
'
if (typeof element.type === 'string') {
'
ReactNativeComponent.createInternalComponent 方法是被注入进来的,注入的是 ReactDOMComponent 类。
最终的结构是 new ReactDOMComponent(element.type,element.props)
生成一个 ReactDOMComponent 的实例返回
'
instance = ReactNativeComponent.createInternalComponent(element);--------(2)
} else if (isInternalComponentType(element.type)) {
instance = new element.type(element);---------------(3)
} else {
'
是我们自定义的类的时候 执行该方法来进行生成 instance 操作。
'
instance = new ReactCompositeComponentWrapper();----------(4)
}
} else if (typeof node === 'string' || typeof node === 'number') {
instance = ReactNativeComponent.createInstanceForText(node);----------(5)
} else {
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : invariant(false) : undefined;
}
instance.construct(node);
instance._mountIndex = 0;
instance._mountImage = null;
return instance;
}
instantiateReactComponent 方法是初始化组件的入口函数,它通过判断 node 的类型来创建不同的react对象。
- 当 node 为空的时候,初始化组件。
- 当 node 为对象,类型 type 字段标记为是字符串,初始化 DOM 标签。否则初始化自定义组件。
- 当 node 为字符串或者数字时,初始化文本组件。
创建了 Component 实例后,调用 component 的 mountComponent 方法,注意到这里是会被批量 mount 的,然后就可以进行渲染。