ReactNative

100 阅读2分钟

1、VirtualDOM的渲染流程

一般情况下,React内我们用这两种方法写一个组件:

function App() {
  return (
    <div>Hello React</div>
  );
}

或者

const App = React.createElement('div', null, 'Hello React');

这两种方法的本质都是调用React.createElement(),该方法返回一个JavaScript对象。这个对象如下所示: 注意 ReactElement是一个函数,React.createElement()的最后一行代码就是调用该函数并返回其结果

var ReactElement = function (type, key, ref, self, source, owner, props) {
  var element = {
    // react中防止XSS注入的变量,也是标志这个是react元素的变量,稍后会讲
    $$typeof: REACT_ELEMENT_TYPE,
    // 构建属于这个元素的属性值
    type: type,
    key: key,
    ref: ref,
    props: props,

    // 记录一下创建这个元素的组件
    _owner: owner,
  };
  return element;
};

经过以上步骤,我们得到的结果是一个Javascript对象,该Javascript对象就是虚拟DOM。接下来,虚拟Dom是怎么变成真实Dom的?通过以下函数:ReactDOM.render(element,container)

那么render函数是如何把虚拟Dom渲染成真实Dom的?

image.png

1、假设现在有一个test文本:“Hello,World!”,我们首先实例化一个ReactDOMTextComponent对象(它叫做渲染器),该对象(渲染器)有一个方法mountComponent。如下所示:

image.png

用文字描述mountComponent做了什么事。第一步:调用DOMLazyTree生成lazyTree对象。lazyTree是一个Javascript对象,其node属性就是该对象对应的真实DOM。然后调用queueChild把Text文本插入其所对应的真实DOM。queueChild如下所示:

function queueChild(parentTree, childTree) {
  if (enableLazy) {
    parentTree.children.push(childTree);
  } else {
    parentTree.node.appendChild(childTree.node);
  }
}

2、假设现有一个原子组件(例如div,span,img),我们首先实例化一个ReactDOMComponent对象。

image.png

不能完全看懂,挑会的讲。第一步,createElement根据虚拟dom的type,创建相应的元素。第二步,_updateDOMProperties更新该元素的属性(例如class,style等等属性)。第三步_createInitialChildren创建该元素的子元素。具体看_createInitialChildren内部,一般直接进入else逻辑:第一种情况是child就是一个text文本,于是调用DOMLazyTree生成一个对象,然后用queueChild把对象加入parentTree的children中。第二种情况child是component,于是调用mountChildren()。不知道mountChildren内部是啥,根据名字猜测和moutComponent功能一样,只不过返回的是数组而已。

3、假设现有一个组合组件。

image.png

看右图_renderValidateComponent会调用构造器的render()方法。renderedElement就是一个虚拟DOM。getType()获取该虚拟DOM的type。根据该type初始化一个渲染器。重复1或者2