加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

React学习 -- React源码(2)Virtual DOM模型

发布时间:2020-12-15 07:16:42 所属栏目:百科 来源:网络整理
导读:VirtualDOM模型负责VirtualDOM底层框架的创建工作,它拥有整套的VirtualDOM标签,并负责虚拟节点的创建、更新、删除等工作。 下面是一个简易的VirtualDOM模型,它并不复杂,只需要具备: 标签名 节点属性:样式,属性,事件等 子节点 标识ID { tagName : 'di

VirtualDOM模型负责VirtualDOM底层框架的创建工作,它拥有整套的VirtualDOM标签,并负责虚拟节点的创建、更新、删除等工作。

下面是一个简易的VirtualDOM模型,它并不复杂,只需要具备:

标签名
节点属性:样式,属性,事件等
子节点
标识ID

{ tagName: 'div',properties: { style: {} 
    },children: [],key: 1
}

virtual DOM中的节点称为ReactNode,分为:ReactElement、ReactFragment、ReactText。其中ReactElement又分为ReactComponentElement和ReactDOMElement。

通过方法createElement创建React虚拟元素

通过JSX创建的虚拟元素最终都会被编译成调用React的createElement方法。

在createElement方法中,对参数做了简单的参数修正(例如,提取config内容,处理children等),然后根据修正过的参数,返回了一个ReactElement对象。

初始化组件入口

当使用React创建组件时,首先会调用instantiateReactComponent,则是初始化组件的入口函数。该函数会根据node类型,区分不同组件的入口。

当node为空时,说明node不存在,则初始化空组件:ReactEmptyComponent.create(instan- tiateReactComponent)
当node类型为对象时,即是DOM标签或自定义组件。初始化DOM标签组件使用方法:ReactNativeComponent.createInternalComponent (element),初始化自定义组件使用方法:ReactCompositeComponentWrapper()。
当node类型为字符串或者数字,则初始化文本组件:ReactNativeComponent.create InstanceForText(node)
如果是其他情况,则不做任何处理。

以下是instantiateReactComponent方法源码:

function instantiateReactComponent(node,parentCompositeType) {
    var instance;
    //空组件(ReactEmptyComponent)
    if (node === null || node === false) {
        instance = ReactEmptyComponent.create(instantiateReactComponent); 
    }
    if (typeof node === 'object') {
        var element = node;
        if (typeof element.type === 'string') {
            // DOM标签(ReactDOMComponent)
            instance = ReactNativeComponent.createInternalComponent(element); 
        } else if (isInternalComponentType(element.type)) {
            // 不是字符串表示的自定义组件暂时无法使用 
            instance = new element.type(element); 
        } else {
            // 自定义组件(ReactCompositeComponent)
            instance = new ReactCompositeComponentWrapper(); 
        }
    } else if (typeof node === 'string' || typeof node === 'number') { 
        // 字符串或数字(ReactTextComponent)
        instance = ReactNativeComponent.createInstanceForText(node);
    } else {
        // 不做处理
    }
    // 设置实例
    instance.construct(node);
    // 初始化参数
    instance._mountIndex = 0;  
    instance._mountImage = null;

    return instance; 
}

关于组件是什么的问题:
这里的组件就是我们在使用react编程时,采用class方法或者直接用函数方法声明的React组件,所有这些组件都最终会被解释为VirtualDOM元素。

文本组件 ##

当node节点为文本节点是,是不算VirtualDOM元素的,但是React为了保持渲染的一致性,将其封装为文本组件:ReactDOMTextComponent。

在执行mountComponent方法时,ReactDOMTextComponent通过transaction.useCreateElement判断该文本是否是通过createElement方法创建的节点,如果是,则为该节点创建相应的标签和标识符。如果不是,React将直接返回文本内容。

DOM标签组件

当开发者在React中使用DOM标签时,例如div,此时的div并不是原生div,其实是React生成的VirtualDOM对象。React的大部分工作都是在VirtualDOM中完成的,这些工作并不会直接操作和污染原生的DOM。这样在性能方面能大有改进,并且降低了直接操作DOM而导致错误的风险。

ReactDOMComponent 对于 Virtual DOM 标签的处理主要包括了两个部分:
1、属性的更新:样式、属性、事件等。
2、子节点的更新:子节点内容、子节点自身、此部分设计diff算法。

1、更新属性

当执行mountComponent方法时,ReactDOMComponent首先会生成标记和标签,通过方法:this. createOpenTagMarkupAndPutListeners(transaction) 来处理DOM节点的属性和事件。

1、如果存在事件,则针对当前的节点添加事件代理:enqueuePutListener(this,propKey,propValue,transaction)
2、如果存在样式,首先会对样式进行合并操作,然后通过CSSPropertyOperations.createMarkupForStyles(propValue,this)方法创建样式。
3、创建属性:DOMPropertyOperations.createMarkupForProperty(propKey,propValue)
4、创建唯一标识符:DOMPropertyOperations.createMarkupForID(this._domID)

当执行receiveComponent方法时,ReactDOMComponent会通过this.updateComponent来更新DOM节点属性(真实DOM)。进行了如下两方面的工作:
1、删除不需要的旧属性
2、更新新属性

2、更新子节点

当执行mountComponent方法时,ReactDOMComponent会通过方法this._createContentMarkup (transaction,props,context)来处理DOM节点的内容。首先获取节点内容,如果节点存在子节点,则通过方法this. mountChildren(childrenToUse,transaction,context)对子节点进行初始化渲染。

和更新属性类似,当执行receiveComponent方法时,ReactDOMComponent会通过this._updateDOMChildren
(lastProps,nextProps,context)来更新DOM内容和子节点(真实DOM)。进行了如下两方面的工作:
1、删除不需要的子节点和内容
2、更新子节点和内容

自定义组件

自定义组件ReactCompositeComponent实现了一整套的React生命周期和setState机制,因此自定义组件实在生命周期环境中进行更新属性、内容和子节点的操作。这些更新操作与ReactDOMComponent的操作类似。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读