Vue.js source code analysis (xviii) Instructions v-for Detailed instructions

We can use the v-forinstruction based on an array to render a list, there are five use, as follows:

<!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-for = "Item in items" > {{Item}} </ P >                                    <-! Array format a, rendering results: <p> 11 < / P> <P> 12 is </ P>     ->          
        < P V-for = "(Item, index) in items" > {{index}} -> {{Item}} </ P >                 <! - two array format, rendering results: <P> 0->. 11 </ P> <P> l-> 12 is </ P> -> 
        < P V-for = "Item in the infos" > {{}} Item </ P >                                    <-! Object format a, rendering results: <p> gege </ p > <p> 12 </ p>-> 
        < P V-for = "(Item, Key) in the infos" > {}} {Key: Item {} {} </ P >                      ! <- object format Second, the rendering results: <p> name: Gege </ P> <P> Age: 12 is </ P> -> 
        < P V-for = "(Item, Key, index) in the infos" > {{}} index: Key {} {}: {{ }} Item </ P >      <-! object format three, rendering results: <P> 0: name: Gege </ P> <P>. 1: Age: 12 is </ P> -> 
    </ div > 
    < Script >
        was app =  new Vue ({ 
            data () { 
                return { 
                    items: [ 11 ,12 is ],                         // V-object may be for 
                    the infos: {name: ' Gege ' , Age: 12 is }             // may be an array 
                } 
            }, 
            EL: ' #app ' 
        }) 
    </ Script >  
</ body > 
< / HTML >

 Very simple, as long as the background provides an interface, returns an array or object, by v-for front-end can be rendered, we have to format the above third object, for example to talk about the source, as follows:

<!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-for="(item,key,index) in infos">{{index}}:{{key}}:{{item}}</p>    
    </div>
    <script>
        var app = new Vue({
            data(){return {infos:{name:'gege',age:12}}},
            el:'#app'
        })
    </script> 
</body>
</html>

 

Source code analysis


 When parsing template, Vue's processFor () -> parseFor () function depending on the parse out the four variables v-for content saved on the property AST object:

function processFor (EL) {             // first row 9367 for instruction processing 
  var exp;
   IF ((getAndRemoveAttr = exp (EL, 'v-for'))) {     // If the v-for acquiring attribute 
    var RES = parseFor (exp );                       // call the function to parse the attribute parseFor 
    IF (res) {                                     // if present res 
      Extend (EL, res);                               // is called extend () added on the object AST 
    } the else { 
      the warn $ 2 ( 
        ( "Invalid V- expression The for: "+ exp) 
      ); 
    } 
  } 
}

parseFor () for parsing the v-for value, and returns an object, as follows:

function parseFor (exp) {                // section 9383 v-for-line parsing attribute exp: v-for value; for example: "(Item, Key, index) in the infos" 
  var inMatch = exp.match (forAliasRE);                       // with regular matching forAliasRE definition line is equal to 9403: / (? [^] *) \ S + (?: in | of) \ S + ([^] *) /; 
  IF (! inMatch) { return }                                   // if not match, return false 
  var RES = {}; 
  RES. for = inMatch [2] .trim ();                               // for value, here equal to: the infos 
  var Alias = inMatch [. 1] .trim () Replace (stripParensRE, ''. ); // removing brackets around this time is equal alias: Item, Key, index 
  var= alias.match iteratorMatch (forIteratorRE);            // matching alias index and 
  IF (iteratorMatch) {                                       // If a match to, i.e., the format is: V-for = "(Item, index) Data in" 
    res.alias = Alias. Replace (forIteratorRE, '');                // for the alias 
    res.iterator1 iteratorMatch = [. 1] .trim ();                     // Get index 
    IF (iteratorMatch [2 ]) { 
      res.iterator2 = iteratorMatch [2 ] .trim (); 
    } 
  } the else { 
    res.alias = Alias; 
  } 
  return RES                                                 // returns the object, such as: {Alias: "Item", for: "the infos", a iterator1: "Key", a iterator2: "index"} 
}

 Here the example of execution in the v-for four attributes associated with the stored v-for, as follows:

Next, when the generate function calls generated rendre genFor () _l generate a corresponding function, as follows:

function genFor (          // rendering instruction v-for 
  EL, 
  State, 
  altGen, 
  altHelper 
) { 
  var exp = EL. for ;                                                  // get the value for the 
  var Alias = el.alias;                                              // Get alias 
  var a iterator1 = el.iterator1? ( "," + (el.iterator1)): '';        // (v-for when the key was the target value) obtain the index 
  var ? = a iterator2 el.iterator2 ( "," + (el.iterator2)) : '';        // / acquisition index (v-for value when the object)) 

  IF ( "Development" ==! 'Production' && 
    State.maybeComponent (el)&&
    el.tag !== 'slot' &&
    el.tag !== 'template' &&
    !el.key
  ) {
    state.warn(
      "<" + (el.tag) + " v-for=\"" + alias + " in " + exp + "\">: component lists rendered with " +
      "v-for should have explicit keys. " +
      "See https://vuejs.org/guide/list.html#key for more info.",
      true /* tip */
    );
  }

  el.forProcessed = true; // avoid recursion
  return (altHelper || '_l') + "(("Exp + + ")," +                patchwork _l function//
    "function(" + alias + iterator1 + iterator2 + "){" +
      "return " + ((altGen || genElement)(el, state)) +
    '})'
}

Last generated render function is equal to:

with(this){return _c('div',{attrs:{"id":"app"}},_l((infos),function(item,key,index){return _c('p',[_v(_s(index)+":"+_s(key)+":"+_s(item))])}))}

Wherein associated with the v-for as follows:

_l((infos),function(item,key,index){return _c('p',[_v(_s(index)+":"+_s(key)+":"+_s(item))

The first parameter _l for our v-for goal, that is, infos, will traverse the object while

_L rendering function executes inside Vue when generating VNode, it is the global renderList, as follows:

function renderList (      // section 3691 v-for line rendering command 
  Val,   
  the render 
) { 
  var RET, I, L, Keys, Key;
   IF (Array.isArray (Val) || typeof Val === 'String') {     / / if val is an array 
    ret = new new the array (val.length);                             // the ret val defined as an array of the same size 
    for (I = 0, L = val.length; I <L; I ++) {                  // iterate array val 
      ret [I] = render (Val [I], I);                                  // sequentially render function call, a parameter value of the parameter is returned vnode index 2, and the results saved to vnode which ret 
    } 
  } the else  IF (typeof val === 'number') {
    ret = new Array(val);
    for (i = 0; i < val; i++) {
      ret[i] = render(i + 1, i);
    }
  } else if (isObject(val)) {
    keys = Object.keys(val);
    ret = new Array(keys.length);
    for (i = 0, l = keys.length; i < l; i++) {
      key = keys[i];
      ret[i] = render(val[key], key, i);
    }
  }
  if(isDef (ret)) {                                        // If ret present (called successfully) 
    ._ isVList = (ret) to true ;                                   // is added to the array _isVList a tag value to true 
  }
   return ret                                                 // last return ret 
}

Finally, packaged together in a VNode array and returns, as a child of other elements (_c third parameter).

Guess you like

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