react中的jsx丶实现原生dom的渲染丶函数组件丶类组件的首次渲染实现
Posted lin-fighting
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react中的jsx丶实现原生dom的渲染丶函数组件丶类组件的首次渲染实现相关的知识,希望对你有一定的参考价值。
jsx
- jsx在babel的帮助下可以转换为react.createElement方法的调用,如
PURE是treeshaking的时候用的,标志这是个纯函数。 - 新老版本的区别
在17之前,我们需要显示引入React,然后Babel转化为React.CreateElement方法,而新的版本中不需要显示引入React,react会自动转化为(Object.s_jsx)方法。 - JSX只是react提供的一个语法糖,react元素是构建react应用的最小 单位。如,let elemtn = < div>13</ div>,这个element就是一个react元素。打印一下看看
{
"type": "div", 元素的类型
"key": null, diff算法用到,用来区分同个父亲不同儿子
"ref": null, 获取真实dom ref的时候会用到
"props": { 属性
"children": "123123"
},
"_owner": null,
"_store": {}
}
这就是一个react元素,所谓的虚拟dom,也就是一个普通的js对象。
- 所谓的渲染就是按照react元素描述的结构,创建真实的dom元素,并插入到root容器内。会由ReactDom这个对象来确保浏览器的真实dom与虚拟dom是一致的。
- 就好比设计师设计出了图纸,工人根据其图纸在指定地点建造房子,房子的造型的图纸是一致的。
JSX表达式
- 表达式就是变量,常量,操作符混合在一起的组合,是可以计算的,而且肯定会有一个返回值。
如
{
"type": "div",
"key": null,
"ref": null,
"props": { //属性
"style": {
"color": "red"
},
"children": "123world"
},
"_owner": null,
"_store": {}
}
返回一个react元素。
- JSX可以作为函数的参数和返回值。
效果是一样的。
元素的更新
- React元素本身是不可变的,即react元素(这个对象是不可扩展的,react17前可以扩展,就好比freeze冻结住了,freeze不可扩展,不可删除,不可修改,浅冻结,seal,不可扩展,可以删除可以修改)的属性,是只读的,不可改。react内部使用了freeze,比如:
可以通过创建新的元素来重新render。ReactDom.render更新不是全量更新,只会更新该更新的部分。
实现原生dom的渲染(react15)
实现createElement以及ReactDom.render
流程
先定义一个Jsx
用babel转换就是
createElement的实现
我们先实现createElement方法
createElement返回一个虚拟dom对象,需要做的处理是children的处理,有多个的话就要数组,一个的话就直接赋值。
效果:第一个是我们自己写的,第二个是React.createElement转化的。
因为后续会实现domdiff,所以必须对文本节点做一些特殊处理,也转换城虚拟dom对象。
定义类型
处理文本节点为虚拟do’m
对每个children进行处理
文本节点已经被处理为虚拟dom了。
render的实现
1 创建真实dom
通过createDom创建真实的dom
Props处理
先处理第一次渲染的Props。第一次主要就是处理style,事件。
props处理后就处理children
判断是多个子节点还是一个文本节点,文本节点直接赋值,多个节点就需要reconclierChildren方法,最后返回出去,因为这是createDom方法。需要返回一个dom
reconclier方法主要是递归拿到children,然后再去render递归遍历这也是react15的缺点,递归遍历无法中断。
函数组件 react15的函数组件是无状态的,所以我们先实现无状态的函数组件,
组件类似于js的函数,接受任意入参props,返回用于描述页面内容的react元素。
可以看到type值已经变成了函数。
也就是
把函数组件当作createElement的第一个值传入。效果是一样的。
实现渲染函数组件
因为我们是自己写的createElement,所以这里也换成自己写的。
首先,在createDom中需要判断函数组件。
调用mountFunctionComponent方法并返回,因为CreateDom需要返回一个dom。
这里直接执行该函数,将props传进去,然后拿到虚拟dom对象,再去调用createDom并返回。
效果
正常渲染。
类组件的首次渲染实现
组件分为内置原生组件和自定义组件,内置组件如p h1 div这些。自定义组件就是类组件,函数组件这些。怎么区分函数组件类组件呢?
在类组件的原型上有一个isReactComponent属性,而函数组件并没有。
实现React.Component
需要一个原型上的isReactComponent属性。
然后
只要在createDom里面判断该vdom是类组件。
new一个实例出来再调用render方法即可拿到react元素。再创建dom返回即可。
可以正常渲染。
总结:
从jsx到原生dom,到函数组件,再到类组件,
基本流程图就是这样,函数组件跟类组件都是返回一个react元素。类组件则是实例的render返回react元素,他们根据原型上的isReactComponent来判断是否是类组件。
以上是关于react中的jsx丶实现原生dom的渲染丶函数组件丶类组件的首次渲染实现的主要内容,如果未能解决你的问题,请参考以下文章
ReactReact全家桶React 概述+虚拟DOM的创建与渲染+JSX