只要是搞前端的对于React这个框架一定不会陌生,React以组件为出发点将一个复杂的页面,划分成若干个不同功能的模块,有些模块还可以抽象出来成为能在项目中复用的组件,甚至还能完全脱离业务成为一套使用不同项目的React组件库;然而React是通过V-DOM这种结构体来编织组件构成不同的页面;接下来就让我们好好看看V-DOM这东西的内部究竟如何。
- V-DOM模型
V-DOM的功能:主要是用来构建出一整套虚拟组件的底层结构和功能;
结构内容:
结构模型:
从上图中可以看出,构成V-DOM的基本单元就是V-Node(或者称为ReactNode),而组成V-Node的基本成分主要由以下这些成分:
1)标签类型:$$typeof
2)节点属性:props(包括属性,事件,子节点,类选择器等)
3)唯一ID值:key
4)引用指针:ref
V-DOM的结构组成图:
其中ReacComponent和ReactElement最为核心,ReactText本文不做深入的探讨。
- ReactFragment
ReactFragment全称是键控集片段,专门用来给一组子元素添加上key值;
原因:对于一般元素来说,可以选择性加上key值,而这个key值就是在diff算法中用来判断该子元素是否在新元素集合中存在,如果存在就直接移动元素,如果没有就插入该元素;而对于如列表渲染或者一组同类(由同一个类创建)的实例重排来说,若没有key,则在渲染后,如果二次渲染,此时React无法判断是否全部删除已存在的旧元素,然后重新渲染全部元素,还是旧元素不变,只插入新元素(此情况下依然可以渲染,但会报错,渲染方式采用前者)。
ReactFragment就是针对该情况采取的一种手段(另一种手段就是直接每个元素加上key,这种方式推荐)。
- ReactElement
ReactElememnt是React中最底层的基本原子,jsx上的标签最终都是变成ReactElement来构造V-DOM;
ReactElement的作用:就是将jsx所写的标签最终转化成一个虚拟的对象,并让对象中至少包含了一些基本属性,如key,ref,props等。
创建ReactElement的方式:
源码结构图:
其中,ReactElement是一个构造函数,它的原理如下图所示,它定义了一些属性来构建和操作虚拟节点,如ref属性,可以通过它来获取该element。
基于ReactElement的基础上,再以不同纬度包装出三个常用的方法:
createElement:通过一些简单的配置项来创建一个虚拟节点;
createFactory:通过输入一个type,构建出一个基于type的工厂函数;
cloneElement:用过输入一个虚拟节点来克隆相同的虚拟节点;
ReactElement还可以细分出基于标签的虚拟节点ReactDOMElement,和基于组件的虚拟绝点ReactComponentElement,这里就不展开细说
缺点:
1)如果用它来写一个相对复杂的页面,则会创建的节点会很多,而且很臃肿,不好维护;
2)没有状态管理,可操作性不强,只能单纯的用来展示。
(如果有兴趣深入研究,可以看React/lib/ReactElement.js)
- ReactComponent
如果项目中采用了React作为前端开发选型,那么一般很少人会直接调用ReactElement这个类来开发组件,绝大部分的开发者都会采用ReactClass中的createClass或者es6中的class(其实是换种形式调用createClass)来构建大型或者复杂的组件;然而ReactClass这个类其实底层是调用了ReactComponent,ReactClass中的一些特性如setState方法(至于setState原理本文不展开,下篇博客就会介绍),其实都是继承了ReactComponent这个类得来的,所以ReactComponent是一切组件的父类。
ReactComponent它在React中的角色就像个幕后人员,因为它不会自己构建组件实例,而是作为一个底层父类来构建出更为灵活的子类来构建实例,所以ReactClass就是它构建实例的代理人。
ReactClass中createClass的全流程
接下来再好好探讨一下createClass的内部结构;
源码:(react/lib/ReactClass.js)
好处:createClass每次调用都可以返回一个构造器,然后通过jsx预发以标签的形式实例化,最终转化为ReactElement虚拟对象;
ReactComponent的好处在于:
1)用jsx语法写V-Node,更易懂简约;
2)ReactComponent创建了一套V-Node的转台管理机制,以便于二次渲染组件。
V-DOM的内容远远不止以上这些,而且V-DOM也只是diff算法的一种实现手段和形式,如果有兴趣深入研究的同学,可以一起交流和研究React这个神奇的框架(以上有什么理解不对的地方可以指出,交流一下)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。