首页 > 作文

Vue.js 源码分析(十七) 指令篇 v

更新时间:2023-04-03 02:52:06 阅读: 评论:0

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true值的时候被渲染。

v-el-if,顾名思义,充当 v-if 的“el-if 块”,可以连续使用:

也可以使用 v-el 指令来表示 v-if 的“el 块”:

挺好理解的,就和大多数的语言的if()….el if()…el逻辑语句是一样的,例如:

<!doctype html><html lang="en"><head>    <meta chart="utf-8">    <title>document</title>    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script></head><body>    <script>        vue.config.productiontip=fal;        vue.config.devtools=fal;    </script>    <div id="app">        <p v-if="no<0">n小于0</p>        <p v-el-if="no==0">no等于0</p>        <p v-el>no大于0</p>    </div>    <script>var app = new vue({el:'#app',data:{no:2}})</script></body></html>

渲染为:

有两个注意点:

  v-el和v-el-if 必须紧跟在带 v-if 或者 v-el-if 的元素之后,一会儿将源码的时候会讲到为什么

  因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,

源码分析

vue内部会把v-if、v-el、v-el-if解析称为一个三元运算符,如果有多个v-el,则三元运算符内再嵌套一个三元运算符,以例子里的为例:

解析模板解析到<p v-if=”no<0″>n小于0</p>这个dom元素时会执行到processif()函数

function processif (el) {               //4 14是什么节日第9402行  解析v-if指令  var exp = getandremoveattr(el, 'v-if');   //获取表达式,例如:"no<0"    if (exp) {                                  //如果存在v-if属性    el.if = exp;                                  //增加if属性    addifcondition(el, {                          //调用addifcondition()函数给el增加一个ifconditions属性,值是一个对象,其中 exp表示当前v-if的值,block是当前ast对象的引用(一会儿给v-el和v-el-if用的)      exp: exp,      block: el    });  } el {                                  //如果不存在v-if属性    if (getandremoveattr(el, 'v-el') != null) {     //如果存在el命令,则在el.el上增加一个el属性      el.el = true;    }    var elif = getandremoveattr(el, 'v-el-if'); //如果存在v-el-if指令,则添加elif属性    if (elif) {      el.elif = elif;    }  }}function addifcondition (el, condition) { //第9453行 增加一个ifconditions属性,  if (!el.ifconditions) {    el.ifconditions = [];                     //如果ifconditions属性不存在则初始化为一个空数组  }  el.ifconditions.push(condition);            //将参数condition这个对象push进来}

对于v-if节点只是增加一个if和ifconditions属性,对于<p v-if=”no<0″>n小于0</p>来说,对应的ast对象增加的属性如下:

解析模板时,对于v-el和v-el-if来说,并没有把当前对应的ast对象加到ast树中,而是把自己对应的ast对象添加到最近的v-if的ifconditions里,代码如下:

if (currentparent && !element.forbidden) {      //第9223行 如果当前对象不是根对象, 且不是style和text/javascript类型script标签  if (element.elif || element.el) {             //如果有elif或el指令存在(设置了v-el或v-elif指令)    pro研究生入党容易吗cessifconditions(element, currentparent);      //则调用processifconditions()函数  } el if (element.slotscope) { // scoped slot    //如果element是作用域插槽    currentparent.plain = fal;    var name = element.slottarget || '"default"';(currentparent.scopedslots || (currentparent.scopedslots = {}))[name] = element;  } el {    currentparent.children.push(element);    element.parent = currentparent;  }}

processifconditions会在之前的ast节点,也就是v-if的ast节点的ifconditions上把当前的ast对象添加进去,如下:

function processifconditions (el, parent) {       //第9421行  解析v-el、v-el-if指令  var prev = findprevelement(parent.children);         //调用findprevelement获取el之前的ast对象(只查找普通元素ast)  if (prev && prev.if) {                                //如果prev存在,且它含有v-if指令    addifcondition(prev, {                                  //则调用addifcondition给prev的ifconditions添加一条语句      exp: el.elif,      block: el    });  } el {    warn$2(      "v-" + (el.elif ? ('el-if="' + el.elif2020江苏高考总分 + '"') : 'el') + " " +      "ud on element <" + (el.tag) + "> without corresponding v-if."    );  }}function findprevelement (children) {           //第9436行 查找children前一个文本ast对象  var i = children.length;  while (i--) {                                   //遍历children,从后开始    if (children[i].type === 1) {                     //如果是普通节点      return children[i]                                //则直接返回该元素    } el {      if ("development" !== 'production' && children[i].text !== ' ') {   //开发模式下,如果该节点不是普通节点,则报错        warn$2(          "text \"" + (children[i].text.trim()) + "\" between v-if and v-el(-if) " +          "will be ignored."        );      }      children.pop();    }  }}

执行完后整个ast对象树如下:

接下来执行generate生成rendre函数时时发现有有if属性就执行genif()函数:

function genif (                //第10205行  //渲染v-if指令  el,  state,  altgen,  altempty) {  el.ifprocesd = true; // avoid recursion                                   //避免递归  return genifconditions(el.ifconditions.slice(), state, altgen, altempty)    //调用genifconditions函数}  function genifconditions (      //第10215行 拼凑if表达式 conditions:比如:[{exp: "ok", block: {…}}]   conditions,  state,  altgen,  altempty) {  if (!conditions.length) {             //如果conditions不存在    return altempt走进电视y || '_e()'             //则直接返回altempty  }  var condition = conditions.shift();    //获取内容,比如:{exp: "no<0", block: {…}}  if (condition.exp) {                   //拼凑三元运算符    return ("(" + (condition.exp) + ")?" + (genternaryexp(condition.block)) + ":" + (genifconditions(conditions, state, altgen, altempty)))  } el {    return ("" + (genternaryexp(condition.block)))  }  // v-if with v-once should genera作文 最好的奖赏te code like (a)?_m(0):_m(1)  function genternaryexp (el) {         //再次调用genelement()函数    return altgen      ? altgen(el, state)      : el.once        ? genonce(el, state)        : genelement(el, state)  }}

最后渲染的render函数为:

_c('div',{attrs:{"id":"app"}},[(no<0)?_c('p',[_v("n小于0")]):(no==0)?_c('p',[_v("no等于0")]):_c('p',[_v("no大于0")])])

其中

(no<0)?_c('p',[_v("n小于0")]):(no==0)?_c('p',[_v("no等于0")]):_c('p',[_v("no大于0")])

就是对应的例子里的v-if、v-el、v-el-if结构了

本文发布于:2023-04-03 02:52:03,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/e4306ca9bdb5eb8c18943dd03cee99b1.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Vue.js 源码分析(十七) 指令篇 v.doc

本文 PDF 下载地址:Vue.js 源码分析(十七) 指令篇 v.pdf

标签:指令   对象   属性   函数
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图