Vue.js source code analysis (17) Instructions v-if, v-else-if and v-else Detailed instructions

v-if conditional instructions for rendering a content. This content will only return truthy value in the expression command when they were rendered.

v-else-if, as the name implies, serve as a v-if "else-if blocks" can be used continuously:

V-else may also be used to indicate instructions of v-if "else block":

Very good understanding of it, and if most of the language () .... else if () ... else statement is the same logic, for example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>
<body>
    <script>
        Vue.config.productionTip=false;
        Vue.config.devtools=false;
    </script>
    <div id="app">
        <p v-if="no<0">n小于0</p>
        <p v-else-if="no==0">no等于0</p>
        <p v-else>no大于0</p>
    </div>
    <script>var app = new Vue({el:'#app',data:{no:</}})2script>
</body>
</html>

Rendered as:

Note there are two points:

  v-else和v-else-ifMust immediately with v-ifor v-else-ifafter the element, while the source code will be mentioned when Why

  Because v-ifa command, so it must be added to an element. But if you want to switch between multiple elements? At this time can be a <template>element as invisible package elements,

 

 Source code analysis


 Vue interior will v-if, v-else, v-else-if parsing a called ternary operator , if there are a plurality of v-else, if the ternary operator then a nested ternary operator to examples in the example:

Template to parse parse < P V-IF = "NO <0" > n-less than 0 </ P > will be executed when the DOM element to processIf () function

function processIf (EL) {                // section 9402 v-if command line parsing 
  var exp = getAndRemoveAttr (EL, 'v-if');    // Get the expression, for example: "NO <0"   
  IF (exp) {                                   // If the attribute v-if present 
    . el if = exp;                                   // increase if properties 
    addIfCondition (el, {                           // call addIfCondition () function to increase a ifConditions el attribute to an object, wherein exp denotes the current value of the v-if , block AST is the current reference object (while a v-else and v-else-if used) 
      exp: exp, 
      Block: EL 
    }); 
  } the else {                                   // If there is no attribute v-if
    IF (! getAndRemoveAttr (EL, 'V-else') = null ) {      // if present else command, else increase in a property el.else 
      EL. else = to true ; 
    } 
    var ELSEIF = getAndRemoveAttr (EL, 'V IF--else '); // if v-elseif commands exist, add attributes elseif 
    IF (elseif) { 
      el.elseif = elseif; 
    } 
  } 
} 
function addIfCondition (EL, for condition Condition) { // increase line 9453 a ifConditions property, 
  IF (! el.ifConditions) { 
    el.ifConditions = [];                      //If the property does not exist ifConditions initialized to an empty array 
  } 
  el.ifConditions.push (condition);             // parameter condition push this object come 
}

For v-if a node if and only increase ifConditions properties, for < P v-if = "NO <0" > n-less than 0 </ P > , the corresponding increase in AST objects following properties:

For v-else and v-else-if it is, and no new AST corresponding to the current object is added to the AST tree, but the AST corresponding to itself to add the object to the nearest ifConditions in v-if the code is as follows :

IF (currentParent &&! element.forbidden) {       // first line 9223 if the current object is not the root object, and not the style and text / javascript type script tag 
  IF (element.elseif || Element. the else ) {              // if or elseif else there is an instruction (provided v-else instruction, or v-elseif) 
    processIfConditions (element, currentParent);       // is called processIfConditions () function 
  } else  IF (element.slotScope) { // scoped // If the element is a slot scope slot 
    currentParent.plain = to false ;
     var name = element.slotTarget || ' "default"'; (currentParent.scopedSlots || (currentParent.scopedSlots = {})) [name] = Element; 
  }else {
    currentParent.children.push(element);
    element.parent = currentParent;
  }
}

 AST will processIfConditions previous node, i.e. the node ifConditions AST v-if the added ast objects into the current, as follows:

function processIfConditions (EL, parent) {        // line 9421 parses v-else, v-else- if instruction 
  var PREV = findPrevElement (parent.children);          // call findPrevElement objects before obtaining EL AST (AST only to find common elements ) 
  IF . (prev prev && IF ) {                                 // If prev is present, and v-if it contains instructions 
    addIfCondition (prev, {                                   // the call addIfCondition ifConditions prev added to a statement 
      exp: el.elseif, 
      Block: EL 
    } ); 
  } the else { 
    The warn $ 2 (
       ? "V-" + (el.elseif ( 'the else-IF = "' + el.elseif + '"'): 'the else') + " " +
      "Element Used ON <" + (el.tag) + "> the without the Corresponding V-IF." 
    ); 
  } 
} 

function findPrevElement (children) {            // line 9436 to find a text before children objects AST 
  var I = children.length ;
   the while (i--) {                                    // iterate children, from the start of 
    IF (Children [I] .Type ===. 1) {                      // If the node is a common 
      return Children [I]                                 // directly returns the element 
    } the else {
       IF ( "Development"! == 'Production' && Children [I] .text! == '') {    //Development mode, if the node is not an ordinary node, the error 
        The warn $ 2  (
          "text \" "+ (Children [I] .text.trim ()) +" \ "BETWEEN V-V and the else-IF (the -if)" + 
          "Will BE ignored." 
        ); 
      } 
      children.pop (); 
    } 
  } 
}

After the implementation of the entire AST object tree are as follows:

Generate performed next generation rendre function if there is always found on the implementation attribute genIf () function:

function genIf (                 // line 10205 // v-if rendering instruction 
  EL, 
  State, 
  altGen, 
  altEmpty 
) { 
  el.ifProcessed = to true ; // Avoid avoid recursion // recursive 
  return genIfConditions (el.ifConditions.slice (), State , altGen, altEmpty)     // call the function genIfConditions 
} 
  
function genIfConditions (       // first row pieced 10215 if expression conditions: for example: [{exp: "OK", Block: {...}}] 
  Conditions, 
  State, 
  altGen, 
  altEmpty 
) { 
  IF (! conditions.length) {             // If the conditions do not exist 
    return altEmpty || '_E ()'              // directly returns altEmpty 
  } 

  var for condition Condition conditions.shift = ();     // get content, such as: {exp: "no <0 ", block: { }} ... 
  IF (condition.exp) {                    // put together ternary operator 
    return ( "(" + (condition.exp) + + (genTernaryExp (condition.block)) + ")?" ":" + (genIfConditions ( Conditions, State, altGen, altEmpty))) 
  } the else {
     return ( "" + (genTernaryExp (condition.block))) 
  } 

  // V-V IF with Once Should Generate code-like (A) _ m (0)?: _m (1) 
  functiongenTernaryExp (EL) {          // called again genElement () function 
    return altGen
       ? altGen (EL, State) 
      : el.once
         ? genOnce (EL, State) 
        : genElement (EL, State) 
  } 
}

Finally, rendering render function is:

_c ( 'div', {attrs: { "id": "app"}}?, [(no <0) _ c ( 'p', [_ v ( "n less than 0")]) :( no == 0 ?) _ c ( 'p', [_ v ( "no equals 0")]): _ c ( 'p', [_ v ( "no greater than 0")])])

among them

?? (No <0) _ c ( 'p', [_ v ( "n less than 0")]) :( no == 0) _ c ( 'p', [_ v ( "no equals 0")]): _ c ( 'p', [_ v ( "no greater than 0")])

It is an example where the corresponding v-if, v-else, v-else-if the structure

 

Guess you like

Origin www.cnblogs.com/greatdesert/p/11127935.html