To be clear, V-if is not an instruction, but a collection of instructions. Generally it contains

  • v-if
  • v-else-if
  • v-else

These three, v-if needs to be at the beginning, V-else needs to be at the end, and you can have several V-else ifs in the middle, and that makes up a series of conditional displays. Follow vUE’s requirements

  • v-else-ifMust followv-ifAfter the element
  • v-elseMust followv-else-ifv-ifAfter the element

Because of the above rules, a two-step parsing is required for v-IF related instructions

  • The first step is inStart End of label parsing, you need tov-ifThe relevant instructions are mounted to the AST element for later processing
  • The second step is inThe entire element tag ends, need to verifyv-else-ifv-elseWhether the use of legal, and then in the corresponding processing
  • One more thing to note here is that for a group ofv-else,v-else-if,v-elseFor elements, you end up generating only one element, not multiple.

Based on the above analysis, the following explanation begins

The first step in parsing is the AST instruction tag

This step occurs at the end of the start tag parsing, when the attribute parsing is complete, so it is easy to mark v-if related instructions.

Before we begin, let’s take a look at a utility function that primarily reads an attribute of the same name in attrList and then removes it from the list

function getAndRemoveAttr(el, name) {
    if(el.attrMap[name] ! =null) {
        const attrList = el.attrList
        for(let i = 0; i < attrList.length; i++){
            if(attrList[i].name === name) {
                attrList.splice(i, 1)
                return el.attrMap[name]
            }
        }
    }
}
Copy the code

Directives are removed here because they are not native to HTML and do not need to be displayed on the tag. (Except for elements with v-pre attributes)

V-if instruction parsing

function processIf(el) {
    const exp = getAndRemoveAttr(el, 'v-if')
    if(exp) {
        el.if = exp;
        el.ifConditions = [{exp, block: el}]
    } else {
        const elseIfExp = getAndRemoveAttr(el, 'v-else-if')
        if(elseIfExp){
            el.elseif = elseIfExp
        } else {
            el.else = true}}}Copy the code

Second, verify the validity of v-else-if and V-else at the end of the tag

In this step, we need to check the validity of v-eles-if and v-else. Here are some details to note:

  • v-ifThe instructions for a series of elements should be elements of the same level
  • v-else-ifThe previous element must containv-eles-ifv-ifinstruction
  • forv-ifText that exists in the series is discarded.

According to the above rules, the following code can be obtained:

function findPrveIfElemnt(children) {
    const i = children.length
    while(i--){
        if(children[i].type === 1) {return children[i]
        } else {
            // Node removal for non-element classes
            children.pop()
        }
    }
}
function parseIf(el) {
    const prev = findPrveIfElemnt(el.children)
    if(prev && prev.if){
        prev.ifConditions.push({
            exp: el.elseif,
            block: el
        })
    } else {
        // Warning message to inform the user of an error
        // Note that if the immediate element is not a V-if directive element, that element is rendered separately and not subject to the v-else-if constraint}}Copy the code

conclusion

Conditional rendering in VUE contains

  • v-if
  • v-else-if
  • v-else

The following details should be followed when using:

  1. v-else-ifMust contain the last sibling element ofv-else-ifv-ifinstruction
  2. v-elseMust contain the last sibling element ofv-else-ifv-if
  3. v-elseAfter thev-else-ifWill be discarded (i.e.,v-elseWill be the end of this sequence of instructions.
  4. v-else,v-else-if,v-ifText nodes between instructions will be discarded
  5. andifYou can only branch one statement at a time, a series of statementsv-ifThe directive also renders only one element