This article has participated in the third “topic writing” track of the Denver Creators Training Camp. For details, check out: Digg Project | Creators Training Camp third is ongoing, “write” to make a personal impact.
Introduction: The topic of this paper is Vue core knowledge and implementation principle, not much to say is to do.
The process of converting a template to a view
- Vue. Js converts the template template into the render function by compilation, which is executed to obtain a virtual node tree
- When the Model is operated on, the Watcher object in the corresponding Dep is fired. The Watcher object calls the corresponding UPDATE to modify the view. This process involves comparing the old and new virtual nodes and then DOM manipulation to update the view based on the comparison results.
Let’s explain some of the concepts above:
- Render functions: Render functions are used to generate the Virtual DOM. Vue recommends using templates to build our application interface. In the underlying implementation, Vue compiles templates into rendering functions, but we can also write rendering functions instead of templates for better control.
- VNode virtual node: This can represent a real DOM node. A VNode can be rendered as a DOM node using the createElement method. Simply put, a VNode can be understood as a node description object, which describes how real DOM nodes should be created.
- Patch (also called patching algorithm) : The core part of the virtual DOM is that it can render the VNode into the real DOM. This process is to compare the differences between the old and new virtual nodes, and then find the nodes that need to be updated according to the comparison results. The actual function is to modify the existing DOM to achieve the purpose of updating the view.
Virtual DOM
What is the virtual DOM
Virtual DOM is a tree based on JavaScript objects, and each node is called VNode. It describes nodes with object attributes. In fact, it is a layer of abstraction of the real DOM, and the tree can be mapped to the real environment through rendering operations. Simply put, the Virtual DOM is a Js object that describes the entire document.
<ul id='myId'>
<li>Item 1</li>
<li>Item 2</li>
<ul>
Copy the code
{
tag: 'ul'
attributes: { id: 'myId' }
children: [
// This is Li]};Copy the code
Advantages of virtual DOM
-
Have the advantage of cross-platform
Because Virtual DOM is based on JavaScript objects and does not depend on the real platform environment, it has cross-platform capabilities.
-
DOM operation is slow, js operation efficiency is high, improve efficiency.
Because the execution speed of DOM operations is not nearly as fast as that of Javascript, a large number of DOM operations are moved to Javascript and patching algorithm is used to calculate the nodes that really need to be updated to minimize DOM operations and significantly improve performance. The Virtual DOM is essentially a cache between JS and DOM. The analogy is CPU and hard disk, since the hard disk is so slow, we put a cache between them: since DOM is so slow, we put a cache between them, JS and DOM. The CPU (JS) only operates on the Virtual DOM, and at the last moment writes changes to the hard disk (DOM).
-
Improved rendering performance
The advantage of Virtual DOM is not in a single operation, but in a large number of frequent data updates, the view can be reasonably and efficiently updated.
Function of virtual DOM
The ultimate goal of the virtual DOM is to render virtual nodes onto the view. However, if you overwrite the old node directly with the virtual node, there will be a lot of unnecessary DOM manipulation. For example, if there are many LI labels under one UL label and only one LI changes, the new UL will be used to replace the old UL, resulting in a waste of performance due to unnecessary DOM operations.
In order to avoid unnecessary DOM operations, the virtual DOM compares the virtual node with the old virtual node (oldVnode) used in the last rendering of the view during the mapping of the virtual node to the view to find the node that really needs to be updated for DOM operations, so as to avoid the operation of other DOM that need no change.
The virtual DOM does two things in vue.js:
- Virtual nodes corresponding to real DOM nodes are provided
- Compare the virtual node VNode with the old virtual node oldVnode and update the view
What is a VNode
Vue.js creates a VNode using the createElement method. Is a JS object that describes a real node
- Vnode is just a name. It is essentially an ordinary object in Javascript, instantiated from the vNode class. If we use this Javascript object to describe a real DOM element, then all properties on that DOM element have corresponding properties on the VNode object.
- A VNode can be understood as a node description object, which describes how real DOM nodes should be created. For example, tag represents the name of an element node, text represents the text of a text node, children represents child nodes, and so on.
- Vnode represents a real DOM element, and all real DOM nodes are created using vNode and inserted into the page. (vnode–>DOM–> view)
- There is a one-to-one mapping between vNodes and views. We can think of a VNode as a Javascript object version of the DOM element.
- The process of rendering a view is to create a VNode, then use the VNode to generate the actual DOM elements, and finally insert the page rendering view.
The role of the VNode
Since a VNode is created each time a view is rendered and then used to create the real DOM inserted into the page, you can cache the vNode created during the last rendering of the view and then compare the newly created vNode with the last cached VNode each time you need to re-render the view. Look at the differences between them, find those differences and modify the real DOM based on them.
VNode attribute Meaning
Tag: indicates the tag name of the current node. Data: indicates the object corresponding to the current node, which contains specific data information. It is of the VNodeData type. Text of the current node elm: real DOM node corresponding to the current virtual node ns: namespace of the current node Context: compilation scope of the current node functionalContext: functional component scope key: ComponentInstance: the instance of the component corresponding to the node. Parent: The parent node of the node. Raw: True for innerHTML and false for textContent isStatic: whether the node is a static node isRootInsert: Whether the node is inserted as a follower isComment: Annotations node isverification: clone node or not isOnce: V-once instruction or notCopy the code
Chestnut 🌰
//html
<div class="test">
<span class="demo">hello,VNode</span>
</div>
Copy the code
//vnode
{
tag: 'div'
data: {
class: 'test'
},
children: [{tag: 'span'.data: {
class: 'demo'
}
text: 'hello,VNode'}}]Copy the code
Vue.js
snaddom
/ / compile h (' a ', {props: {href: 'http://www.baidu.com'}}, "Hello word"); / / {" sel ":" a ", "data" : {props: {href: 'http://www.baidu.com'}}, "text" : "Hello word"} / / real nodes<a href="http://www.baidu.com">Hello word</a>
Copy the code
The type of the Vnode
A VNode is an object in Javascript, and the only difference between different types of VNodes is their properties, or rather their valid properties. This is because when creating a VNode using the VNode class, invalid properties are assigned to undefined or false by default when setting attributes for the instance. For invalid attributes on vNodes, simply ignore them.
Comment node
export const createEmptyVNode = text= >{
const node = new VNode();
node.text = text;
node.isComment = true;
return node
}
(1) a comment node has only two valid attributes -----text and isComment. The rest of the attributes are undefined or false by default.
// The corresponding vnode is as follows:
{
text:"Comment node".isComment:true
}
// Comment the node
Copy the code
Text node
export function createTextVNode(val){
return new VNode(undefined.undefined.undefined.String(val))
}
// (1) When a text vnode is created, it has only one text attribute
// VNode of text type
{
text:"Hello Berwin"
}
Copy the code
Clone node
(1) Cloning node is to assign the attributes of the existing node to the new node, so that the attributes of the newly created node and the cloned node are consistent, so as to achieve the cloning effect.
(2) Function: Optimize static nodes and slot nodes.
(3) Take the static node as an example. When a certain state in the component changes, the current component will re-render the view through the virtual DOM. Because the content of the static node does not change, it does not need to perform the rendering function to regenerate the VNode except for the first rendering to obtain the VNode. Therefore, a clone of the VNode is created using the same method as the clone node, and the clone node is used for rendering. This improves performance by eliminating the need to re-execute the rendering function to generate vNodes with new static nodes. (4) When cloning the existing node, it only needs to assign all the attributes of the existing node to the new node.
(5) The only difference between the clone node and the cloned node is the feature of isempirical; the clone node has the feature of isempirical is true, while the clone original node has the feature of empirical is false.
export function cloneVNode(vnode,deep){
const cloned = new VNode(
vnode.tag,
vnode.data,
vnode.children,
vnode.text,
vnode.elm,
vnode.context,
vnode.componentOptions,
vnode.asyncFactory
)
cloned.ns = vnode.;
cloned.isStatic = vnode.isStatic;
cloned.key = vnode.key;
cloned.isComment = vnode.isComment;
cloned.isCloned = true;
if(deep&&vnode.children){
cloned.chlidren = cloneVNodes(vnode.children);
}
return cloned;
}
Copy the code
Element nodes
(1) Element nodes usually have the following four valid attributes.
Tag: Tag is the name of a node, such as ul, P, li, and div. Data: This property contains data on nodes, such as attrs, class, and style. Children: indicates the list of children of the current node. Context: This is the vue.js instance of the current component.
// The real element node
<p><span>Hello</span><span>Berwin</span></p>
// Corresponding vnode
{
children:[VNode,VNode],
context: {... },data: {... },tag:"p". }Copy the code
Component node
ComponentOptions: Options parameters for component nodes, including propsData, Tag, and children. ComponentInstance: An instance of a component, i.e. Vue.js. In fact, in vue.js, every component is an instance of vue.js.
// a component node
<child></child>
// The corresponding vnode is as follows:
{
componentInstance: {... },componentOptions: {... },context: {... },data: {... },tag:"vue-component-1-child". }Copy the code
Functional component
A functional component is similar to a component node in that it has two unique properties functionalContext and functionalOptions.
{
functionalContext: {... },functionalOptions: {... },context: {... },data: {... },tag:"div". }Copy the code
Patch
updateChildren
oldStartIdx
,newStartIdx
,oldEndIdx
As well asnewEndIdx
The old and the newVNode
Index on both sides, at the same timeoldStartVnode
,newStartVnode
,oldEndVnode
andnew EndVnode
Points to each of these indexesvnode
. The entire traversal needs to be inoldStartIdx
Less thanoldEndIdx
andnewStartIdx
Less thannewEndIdx
(Here, for simplicity, it is calledsameVnode
For similar).
- when
oldStartVnode
When they don’t exist,oldStartVnode
If I move to the right,oldStartIdx
add1
. - when
oldEndVnode
When they don’t exist,oldEndVnode
If I move to the right,oldEndIdx
Reduction of1
. oldStartVnode
andnewStartVnode
Similar,oldStartVnode
andnewStartVnode
All moving to the right,oldStartIdx
andnewStartIdx
All increase1
.
oldEndVnode
andnewEndVnode
Similar,oldEndVnode
andnewEndVnode
All moving to the left,oldEndIdx
andnewEndIdx
All reduction1
.
oldStartVnode
andnewEndVnode
Similar, then theoldStartVnode.elm
Move to theoldEndVnode.elm
After the node of. thenoldStartIdx
Move back one,newEndIdx
Move forward one.
oldEndVnode
andnewStartVnode
When similar, putoldEndVnode.elm
Inserted into theoldStartVnode.elm
The front. In the same way,oldEndIdx
If I move forward one bit,newStartIdx
Move back one.
When none of the above is true.
Generate a hash table with a key corresponding to the old VNode.
The createKeyToOldIdx function creates a key-index mapping agent to traverse the sameNode when comparing two arrays of child nodes. Improve performance.
function createKeyToOldIdx (children, beginIdx, endIdx) {
let i, key
const map = {}
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key
if (isDef(key)) map[key] = i
}
return map
}
Copy the code
The resulting object is an object with the children’s key as the property and the increasing number as the property value for example
children = [{
key: 'key1'
}, {
key: 'key2'
}]
// The map generated at the end
map = {
key1: 0.key2: 1,}Copy the code
So oldKeyToIdx is the hash table corresponding to the key and the oldVnode key to see if the corresponding oldVnode can be found.
-
If oldVnode does not exist, a new node is created and newStartVnode moves to the right.
-
If the node is found:
-
It is similar to newStartVnode. Assign undefined to this position in the map (to ensure that the key is unique). Elm in front of oldStartvNode. elm, then move index back one bit.
-
If it does not match sameVnode, only a new node can be created and inserted into the child node of parentElm, with newStartIdx moved back one bit.
-
After the loop
OldStartIdx is greater than oldEndIdx, and the new nodes with no comparison are added to the end of the queue.
If newStartIdx > newEndIdx, new nodes exist and are deleted.
Praise support, hand left lingering fragrance, with rongyan, move your rich little hands yo, thank you big guy can leave your footprints.
Past wonderful recommendation
Front-end performance optimization for actual combat
Talk about annoying regular expressions
Obtain file BLOB stream address to achieve the download function
Git Git
Easy to understand Git introduction
Git implements automatic push
How do I use Git in my work
Interview Recommendations
Front ten thousand literal classics – the foundation
Front swastika area – advanced section
Node series teaching and more wonderful see: personal homepage