preface
Learn vue source code, from 0 to 1…
Frameworks such as Vue and React convert their templates to the virtual DOM and then perform subsequent operations. How to convert a DOM to a virtual DOM? Here I use a recursive way to do simple transformation, which is different from the basic implementation of Vue and React, just to better understand DOM and virtual DOM.
Why do we need the virtual DOM in the first place?
In our daily development, DOM often needs to be modified, and frequent operation of real DOM will trigger redrawing and rearrangement, which seriously affects page performance. Therefore, virtual DOM is proposed. As an abstraction of real DOM, DOM information is stored in the form of objects, cached in memory, and real DOM is updated at a time to improve performance.
Prepare knowledge
1. What is DOM?
For detailed DOM native apis, see MDN:DOM
DOM is the interface of JavaScript to operate web pages, fully known as “Document Object Model”. DOM model uses a logical tree to represent a document. The end of each branch of the tree is a node, and each node contains objects.
A node is the smallest unit of a DOM tree. The tree structure of a Document is composed of nodes with different column types (Document, Element, Text).
See MDN:NODE for details about NODE’s native API
Write a simple DOM structure in an HTML fileCopy the code
<div id="root" class="c1">
<p>hello</p>
</div>
<script>
const root = document.querySelector('#root')
console.dir(root)
console.dir(root.childNodes)
</script>
Copy the code
Print out the DOM structure at the console
2. NODE properties
-
NodeName: node name, uppercase if element, with # in front of other names.
-
NodeType: Specifies the node type, usually represented by a number. 1 represents element(which can also be represented by Node.element_node) and 3 represents text(node.text_node).
If it is Element, nodeName === tagName
If it is text, then nodeName = #text, tagName = undefined
-
NodeValue: The value of the current node. For text and comment nodes, nodeValue returns the text content of the node, for attribute nodes, the value of the attribute, and for document and Element nodes, null
The real DOM => virtual DOM
Create a VDom class with attributes: Tag, data, value, Type, children
Starting with the DOM root node, each node is instantiated as a VDom, recursively traversing its children
For text nodes, there are no children, only one text attribute
// Create a VDom class
class VDom {
constructor(tag, data, value, type) {
this.tag = tag && tag.toLowerCase() / / the node name
this.data = data / / property
this.value = value // Text data
this.type = type // Node type
this.children = []
}
appendChild(vnode) {
this.children.push(vnode)
}
}
function getVNode(node) {
let nodeType = node.nodeType
let _vnode = null
if (nodeType === 1) {
/ / element
let tag = node.nodeName
let attrs = node.attributes
let _attrObj = {}
for (let i = 0; i< attrs.length; i++) {
_attrObj[attrs[i].nodeName] = attrs[i].nodeValue
}
_vnode = new VDom(tag, _attrObj, undefined, nodeType)
let children = node.childNodes
for (let i = 0; i < children.length; i++) {
_vnode.appendChild(getVNode(children[i]))
}
} else if (nodeType === 3) {
/ / text
_vnode = new VDom(node.nodeName, undefined, node.nodeValue, nodeType)
}
return _vnode
}
const vroot = getVNode(document.querySelector('#root'))
console.log(vroot)
Copy the code
The final converted VDom format is as follows:
Virtual DOM => real DOM
Here’s the thing: What if you create an element node with a nodeName?
How do I create a text node from a piece of text?
CreateElement: Creates an element by specifying its name
CreateTextNode: Creates a text node
The idea is similar to the above, which is to create the DOM recursively and append it to the parent component
function parseVNode(vnode) {
let type = vnode.type
let rdom = null
if (type === 1) {
rdom = document.createElement(vnode.tag)
/ / element
let attrs = vnode.data
for (let key in attrs) {
rdom.setAttribute(key, attrs[key])
}
let children = vnode.children
for (let i = 0; i < children.length; i++) {
rdom.appendChild(parseVNode(children[i]))
}
} else if (type === 3) {
/ / text
rdom = document.createTextNode(vnode.value)
}
return rdom
}
const realRoot = parseVNode(vroot)
console.log(realRoot)
document.body.appendChild(realRoot)
Copy the code
conclusion
This article is mainly in a recursive way, with native JS to achieve real DOM and virtual DOM direct transformation, is a very basic knowledge point, now many people with the framework for a long time will not use the native method, do these small exercises for the understanding of native JS and reading framework source code are good.
If there is an error in the article please point out in time, don’t blame mo!
Without further ado, go on studying ~~~