$mount template parse, we introduced the parse part of Compile, so far we have completed an HTML string template parse into an AST syntax tree process. The next step is that we need to mark the AST nodes as static nodes with the optimize method. Optimization was made for comparing the old and new VNode tree structures in the subsequent patch process. Nodes marked as static are ignored in subsequent diff algorithms without detailed comparisons.
src/compiler/optimizer.js
Copy the code
export functionoptimize (root: ? ASTElement, options: CompilerOptions) {if(! root)return/ / staticKeys that won't be change static properties of ast isStaticKey = genStaticKeysCached (options. StaticKeys | |' ') isPlatformReservedTag = options.isReservedTag || no // first pass: Mark all non-static nodes. // First step marks all static nodes in the AST. Mark static roots. // Step 2 mark all parent nodes of the AST (i.e. child root nodes) markStaticRoots(root,false)}Copy the code
First mark all static nodes:
function isStatic (node: ASTNode): boolean {
if(Node.type === 2) {// expressionreturn false
}
if(node.type === 3) {// Text nodereturn true} // Handle special tagsreturn!!!!! (the node. The pre | | (/ / v - pre tag! node.hasBindings && // no dynamic bindings ! node.if && ! node.for && // not v-if or v-for or v-else ! isBuiltInTag(node.tag) && // not a built-in isPlatformReservedTag(node.tag) && // not a component ! isDirectChildOfTemplateFor(node) && Object.keys(node).every(isStaticKey) )) }Copy the code
The TYPE field of ASTNode is used to identify the type of the node. For details, see the AST node definitions in the previous section:
Type 1 represents the element,
Type 2 denotes an interpolation expression,
Type 3 indicates plain text.
As you can see, when marking ASTElement, the static tags of all child element nodes are checked in turn to see if the element is static. The markStatic function above uses a depth-first traversal of a tree data structure, implemented recursively. Next, mark the static tree:
function markStaticRoots (node: ASTNode, isInFor: boolean) {
if(node.type === 1) {// Used to mark static nodes in v-for. This property tells renderStatic(_m) to generate a new key for this node, avoiding patch errorsif (node.static || node.once) {
node.staticInFor = isInFor
}
// For a node to qualify as a static root, it should have children that
// are not just static text. Otherwise the cost of hoisting out will
// outweigh the benefits and it// If a node wants to be a static root, its children can't just be static text. Otherwise, extracting it separately is not as good as always updating it when rerendering. if (node.static && node.children.length && ! ( node.children.length === 1 && node.children[0].type === 3 )) { node.staticRoot = true return } else { node.staticRoot = false } if (node.children) { for (let i = 0, l = node.children.length; i < l; i++) { markStaticRoots(node.children[i], isInFor || !! node.for) } } if (node.ifConditions) { for (let i = 1, l = node.ifConditions.length; i < l; i++) { markStaticRoots(node.ifConditions[i].block, isInFor) } } } }Copy the code
There’s nothing special about the markStaticRoots function, just another layer of filtering for static nodes.
conclusion
Optimizer aims to label the nodes of the syntax tree with static and staticRoot attributes. To traverse the first round, mark the static property:
Check whether the children of node are static. If there are any non-static children, change the parent to static = false and pass through the second round with staticRoot
Tag static or staticRoot, which is of type === 1. Nodes with the V-once directive are also marked staticRoot to avoid excessive optimization. Only nodes whose static text is a child are not marked as staticRoot of the children node
Give me a star, Github, if you like
Thanks muwoo for the idea