ZF_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来判断是否是类组件。

猜你喜欢

转载自blog.csdn.net/lin_fightin/article/details/120424792
今日推荐