Preface
Sometimes some interviews are often askedv-for
andv-if
Who has the highest priority? Here we will answer this question by analyzing the source code.
The following content is analyzed based on what we are discussing when we talk about v-model, so you can read this article before reading the following content.
Continue to start from compilation
The following examples start with the analysis:
new Vue({ el:'#app', template:` <ul> <li v-for="(item,index) in items" v-if="index!==0"> {{item}} </li> </ul> ` })
From the previous article, we can see that there are three steps to compile.
- parse: parsing template strings to generate AST syntax tree
- optimize: Optimize the syntax tree, mark static nodes mainly in time, and improve the performance of updating pages
- codegen: Generate js code, mainly render function and staticRenderFns function
We will follow these three steps again to analyze the above examples.
parse
parseDuring the process, a large number of regular expressions will be used to parse the template. The example at the beginning will be parsed into the followingAST
node:
// Actually, ast has many attributes, I only show the attributes involved in analysis hereast = { 'type': 1, 'tag': 'ul', 'attrsList': [], attrsMap: {}, 'children': [{ 'type': 1, 'tag': 'li', 'attrsList': [], 'attrsMap': { 'v-for': '(item,index) in data', 'v-if': 'index!==0' }, // attributes parsed by v-if 'if': 'index!==0', 'ifConditions': [{ 'exp': 'index!==0', 'block': // Point to el itself }], // V-for parsed properties 'for': 'items', 'alias': 'item', 'iterator1': 'index', 'parent': // Point to its parent node 'children': [ 'type': 2, 'expression': '_s(item)' 'text': '{{item}}', 'tokens': [ {'@binding':'item'}, ] ] }] }
forv-for
Instructions, except for recordingattrsMap
andattrsList
, there will be new onesfor
(corresponding to the object or array to be traversed),alias
,iterator1
,iterator2
correspondv-for
The first, second, and third parameters in the directive binding content. The example at the beginning does not have the third parameter, so there is noiterator2
property.
forv-if
Instructions,v-if
The bound content in the command is taken out and placedif
Initialize at the same timeifConditions
The attribute is an array, and then the object is stored in it:{exp,block}
,inexp
Storev-if
The content bound in the command,block
Point toel
。
optimizeThe process will not be analyzed here, because there are no static nodes in this example.
codegen
Previous article fromconst code = generate(ast, options)
Begin to analyze the process of generating code.generate
It will be called internallygenElement
Used to parseel
, that isAST
Syntax tree. Let's take a lookgenElement
Source code:
export function genElement (el: ASTElement, state: CodegenState): string { if () { = || } if ( && !) { return genStatic(el, state) } else if ( && !) { return genOnce(el, state) // In fact, from this we can first know why v-for is higher priority than v-if. // Because when parsing the ast tree to generate render function code, the attributes involved in v-for in the ast tree will be parsed first // Then parse the properties involved in v-if in the ast tree // And genFor will set it to true to prevent repeated parsing of v-for related attributes } else if ( && !) { return genFor(el, state) } else if ( && !) { return genIf(el, state) } else if ( === 'template' && ! && !) { return genChildren(el, state) || 'void 0' } else if ( === 'slot') { return genSlot(el, state) } else { // component or element let code if () { code = genComponent(, el, state) } else { let data if (! || ( && (el))) { data = genData(el, state) } const children = ? null : genChildren(el, state, true) code = `_c('${}'${ data ? `,${data}` : '' // data }${ children ? `,${children}` : '' // children })` } // module transforms for (let i = 0; i < ; i++) { code = [i](el, code) } return code } }
Next, take a lookgenFor
andgenIf
Function source code:
export function genFor (el, state , altGen, altHelper) { const exp = const alias = const iterator1 = el.iterator1 ? `,${el.iterator1}` : '' const iterator2 = el.iterator2 ? `,${el.iterator2}` : '' = true // avoid recursion return `${altHelper || '_l'}((${exp}),` + `function(${alias}${iterator1}${iterator2}){` + `return ${(altGen || genElement)(el, state)}` + //Recursively call genElement '})' }
In our case, when he handles itli
ofast
When the tree is called firstgenElement
, processed tofor
Attributes, at this timeforProcessed
It is a virtual value, and it is called at this timegenFor
deal withli
The treev-for
Related attributes. Then callgenElement
deal withli
Tree, at this timeforProcessed
existgenFor
has been marked astrue
. thereforegenFor
Will not be executed, then executedgenIf
Processing andv-if
Related attributes.
export function genIf (el,state,altGen,altEmpty) { = true // avoid recursion // Call genIfConditions to process the main properties return genIfConditions((), state, altGen, altEmpty) } function genIfConditions (conditions, state, altGen, altEmpty) { if (!) { return altEmpty || '_e()' // _e is used to generate empty VNode } const condition = () if () { //That is, the v-if binding value, in the example, it is 'index!==0' // Generate a js code string with three-item operator return `(${})?${ genTernaryExp() }:${ genIfConditions(conditions, state, altGen, altEmpty) }` } else { return `${genTernaryExp()}` } // v-if with v-once should generate code like (a)?_m(0):_m(1) function genTernaryExp (el) { return altGen ? altGen(el, state) : ? genOnce(el, state) : genElement(el, state) } }
refer toDetailed answers to front-end advanced interview questions
Finally,codegenThe generated js code is as follows:
function render() { with(this) { return _c('ul', _l((items), function (item, index) { return (index !== 0) ? _c('li') : _e() }), 0) } }
in:
-
_c
: CallcreateElement
Go to createVNode
-
_l
:renderList
Functions, mainly used to render lists -
_e
:createEmptyVNode
Functions are mainly used to create emptyVNode
Summarize
Why is v-for more priority than v-if? In summary, there are three processes for compilation.parse
->optimize
->codegen
. existcodegen
During the process, the analysis will be performed firstAST
and in the treev-for
Related attributes, then parse andv-if
Related attributes. In addition, you can also knowVue
rightv-for
andv-if
How to deal with it.
The above is the detailed content of why v-for is more priority than v-if plateau analysis. For more information about vue priority v-for v-if, please follow my other related articles!