preface

Virtual DOM is like a Virtual space to React. React works almost all based on Virtual DOM. Among them, the Virtual DOM model is responsible for the construction of the underlying framework. It has a set of Virtual DOM tags and is responsible for the construction, update and deletion of Virtual nodes and their attributes. So how does the Virtual DOM model build Virtual nodes and update node attributes?

The concept and birth background of Virtual DOM

First look at the concept of DOM, DOM is the Document Object Model(Document Object Model) is a tree structure representing page elements. The Virtual DOM, an abstraction of the real DOM, is an object described in JavaScript. The Virtual DOM was born with React and was introduced by Facebook. Its appearance is mainly for balancing development efficiency and performance. After React, Vue 2.0 introduced the concept of Virtual DOM.

Advantages of Virtual DOM

  1. Performance guarantee
  2. Improve development efficiency
  3. Excellent cross-platform capabilities

Why don’t we just render DOM updates?

Real DOM

We can see one in the picture aboveDOMTags have a lot of attributes,DOMThe operation is very expensive and seemingly complexVirtual DOMIt’s actually more efficient.

Second,DOMThe basic elements required for the tag

What are the basic element tags required for a DOM tag in the Virtual DOM model? In fact, a simple Virtual DOM model is not complicated, it only needs to have a DOM tag required by the basic elements:

  • Tag name
  • Node properties (including styles, properties, events, and so on)
  • Child nodes
  • logoid

Example code is as follows:

{// tagName: 'div', // attribute prototies: {// style: {}}, // children: [], // unique identifier key: 1}Copy the code
{ type: 'h1', props: { className: 'title', children: 'Hello World! ' }, key: null, ref: null }Copy the code

The Virtual DOM model is more than that, of course, but it also relies on these basic elements. Now let’s demystify it.

Nodes in the Virtual DOM are called ReactNodes and are divided into three types: ReactElement (element type), ReactFragment, and ReactText (text type). ReactElement is divided into ReactComponentElement and ReactDOMElement. In simple terms: element type (component type, DOM type), Fragment type, text type.

Here are the basic elements required for the different types of nodes in a ReactNode:

type ReactNode = ReactElement | ReactFragment | ReactText;
type ReactElement = ReactComponentElement | ReactDomElement;
type ReactDOMElement = {
  type: stirng,
  props: {
    children: ReactNodeList,
    className: string,
    etc,
  },
  key: string | boolean | number | null,
  ref: string | null
};
type ReactComponentElement<TProps> = {
  type: ReactClass<TProps>,
  props: TProps,
  key: string | boolean | number | null,
  ref: string | null
};
type ReactFragment = Array<ReactNode | ReactEmpty>;
type ReactNodeList = ReactNode | ReactEmpty;
type ReactText = string | number;
type REactEmpty = nul | undefined | boolean;
Copy the code

So how does the Virtual DOM model create elements based on these node types?

Second, createReactThe element

Here is a snippet of JSX and compiled JavaScript:

const Nav, Profile; / / input (JSX); const app = <Nav color='blue><Profile>click</Profile></Nav>; Const app = react. createElement(Nav, {color: 'blue'}, react. createElement(Profile, null, "click"));Copy the code

Online Babel compiler

Virtual elements created with JSX will eventually be compiled into createElement methods that call React.

// createElement returns a ReactElement instance with a simple argument correction. / / is the instance of virtual element ReactElement. The createElement method = function (type, the config, children) {/ / var propName initialization parameters; var props = {}; var key = null; var ref = null; var self = null; var source = null; // If (config! = null) { ref = config.ref === undefined ? null : config.ref; key = config.key === undefined ? null : '' + config.key; self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; For (propName in config) {if (config.hasownProperty (propName) &&! RESERVED_PROPS.hasOwnProperty(propName)) { props[propName] = config[propName]; }}} // Handle children, all mount to the children property of props. Var childrenLength = arguments.length - 2; var childrenLength = children.length - 2; if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { var childArray = Array(childrenLength); for (var i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } props.children = childArray; } // If a prop is empty and there is a default prop, assign the default prop to the current prop if (type && type.defaultprops) {var defaultProps = type.defaultprops;  for (propName in defaultProps) { if (typeof props[propName] === 'undefined') { props[propName] = defaultProps[propName];  }}} / / return a ReactElement instance object return ReactElement (type, key, ref, the self, the source, ReactCurrentOwner. Current, props); };Copy the code

The Virtual DOM model creates Virtual elements with createElement, but how do you create components?

Initialize the component entry

When using the React to create components, the first is called instantiateReactComponent, this is the entry function initializes the component, it by judging the node type to distinguish between different components of the entrance.

  • whennodeIf is empty, indicates thatnodeIf it does not exist, initialize the empty componentReactEmptyComponent.create(instantiateReactComponent).
  • whennodeIf the type is object, it isDOMTag component or custom component, then ifelementType of word

Character string, the initialization of the DOM label component ReactNativeComponent. CreateInternalComponent (element), otherwise the initialization of custom components ReactCompositeComponentWrapper ().

  • whennodeInitializes the text component when the type is string or numberReactNativeComponent.createInstanceForText(node).
  • In other cases, no action is taken.

Text component

A text node does not count as a Virtual DOM element, but React encapsulates it as a text component, ReactDOMTextComponent, to maintain consistency in rendering.

When performing mountComponent method, ReactDOMTextComponent through transation. UseCreateElement judge whether the text through the createElement method method to create nodes, if it is, Create the corresponding label and domID for the node, so that each text node has its own unique identity like other React nodes, and also has the rights of Virtual DOM diff. But if the text is not created with createElement, React will no longer create and domID identifiers for it, instead returning the text content directly.

DOM tag component

The Virtual DOM model covers almost all native DOM tags, such as

,

, < SPAN >, and so on. When developers use React, the

tag is not a native

tag. It is actually a Virtual DOM object generated by React with the same tag name. React does most of its work in the Virtual DOM. The Virtual DOM is like an isolated sandbox for the native DOM, so React processing does not directly manipulate and pollute the native DOM. This keeps performance efficient and stable. It also reduces the risk of errors caused by direct manipulation of the native DOM.

The ReactDOMComponent handles Virtual DOM tags in the following two parts:

  • Update of attributes, including update style, update attributes, processing events, etc.
  • Update of child node, including update content, update child node, this part involvesdiffAlgorithm (diffSee the reference documentation for the algorithmThe key property in the React list).
1. Update attributes

When the mountComponent method is executed, the ReactDOMComponent first generates tags and labels, Through this. CreateOpenTagMarkupAndPutListeners (transaction) to deal with DOM node properties and events.

  • If there is an event, add an event broker for the current node by calling ‘enqueuePutListener(this,

` propKey propValue, transaction).

  • If a style exists, the style is merged firstObject.assign({}, props.style)And then through

CSSPropertyOperations. CreateMarkupForStyles (propValue, this) to create a style.

  • throughDOMPropertyOperations.createMarkupForProperty(propKey, propValue)Create properties.
  • throughDOMPropertyOperations.createMarkupForID(this._domID)Create a unique identifier.
2. Update child nodes

When the mountComponent method is executed, the ReactDOMComponent processes the content of the DOM node through this._createcontentMarkup (transaction, props, context).

When the receiveComponent method is executed, The ReactDOMComponent updates the DOM content and child nodes with this._updatedomChildren (lastProps, nextProps, Transaction, context).

First, remove unwanted child nodes and content. If the old node exists but the new node does not, the current node is deleted after the update. In this case, run the this.updateChildren(null, transaction, context) method. If the old content exists but the new content does not, the current content was deleted after the update. In this case, the this.updatetextContent (” “) method is executed.

Then update the child nodes and content. UpdateChildren (nextChildren, Transaction, Context) if a new child exists, the child is updated. If new content exists, the content is updated, at which point the method this.updatetExtContent (” + nextContent) is executed.

Custom components

ReactCompositeComponent custom components implement a full set of React lifecycle and setState mechanisms, so custom components update properties, content, and child nodes in a lifecycle environment. These update operations are similar to those of the ReactDOMComponent.


Seven,

React Fiber Has been updated to the Virtual DOM since version 16, but the main ideas remain the same.

Comparison between the Virtual DOM and the real DOM and application scenarios

First render speed performance Speed performance when updating data Applicable scenario
Virtual DOM general fast It works almost everywhere, slower for first rendering and some special scenes, but acceptable.
Real DOM fast general First rendering and small data operations performed better, while update operations were slower for large data volumes.

The performance advantage of Virtual DOM is not completely reflected in “fast”, but in that it also has a better overall performance.

Reference Documents:

coordinate

The key property in the React list

React Fiber

Virtual DOM and kernel (Important)