文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue中v-for比v-if高的原因是什么

2023-07-05 12:52

关注

本篇内容介绍了“vue中v-for比v-if高的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

继续从编译出发

以下面的例子出发分析:

new Vue({    el:'#app',    template:`        <ul>            <li v-for="(item,index) in items" v-if="index!==0">                {{item}}            </li>        </ul>    `})

从上篇文章可以知道,编译有三个步骤

我们再次顺着这三个步骤对上述例子进行分析。

parse

parse过程中,会对模板使用大量的正则表达式去进行解析。开头的例子会被解析成以下AST节点:

// 其实ast有很多属性,我这里只展示涉及到分析的属性ast = {  'type': 1,  'tag': 'ul',  'attrsList': [],  attrsMap: {},  'children': [{    'type': 1,    'tag': 'li',    'attrsList': [],    'attrsMap': {      'v-for': '(item,index) in data',      'v-if': 'index!==0'     },     // v-if解析出来的属性    'if': 'index!==0',    'ifConditions': [{      'exp': 'index!==0',      'block': // 指向el自身    }],    // v-for解析出来的属性    'for': 'items',    'alias': 'item',    'iterator1': 'index',    'parent': // 指向其父节点    'children': [      'type': 2,      'expression': '_s(item)'      'text': '{{item}}',      'tokens': [        {'@binding':'item'},      ]    ]  }]}

对于v-for指令,除了记录在attrsMapattrsList,还会新增for(对应要遍历的对象或数组),aliasiterator1,iterator2对应v-for指令绑定内容中的第一,第二,第三个参数,开头的例子没有第三个参数,因此没有iterator2属性。

对于v-if指令,把v-if指令中绑定的内容取出放在if中,与此同时初始化ifConditions属性为数组,然后往里面存放对象:{exp,block},其中exp存放v-if指令中绑定的内容,block指向el

optimize 过程在此不做分析,因为本例子没有静态节点。

codegen

上一篇文章从const code = generate(ast, options)开始分析过其生成代码的过程,generate内部会调用genElement用来解析el,也就是AST语法树。我们来看一下genElement的源码:

export function genElement (el: ASTElement, state: CodegenState): string {  if (el.parent) {    el.pre = el.pre || el.parent.pre  }  if (el.staticRoot && !el.staticProcessed) {    return genStatic(el, state)  } else if (el.once && !el.onceProcessed) {    return genOnce(el, state)  // 其实从此处可以初步知道为什么v-for优先级比v-if高,  // 因为解析ast树生成渲染函数代码时,会先解析ast树中涉及到v-for的属性  // 然后再解析ast树中涉及到v-if的属性  // 而且genFor在会把el.forProcessed置为true,防止重复解析v-for相关属性  } else if (el.for && !el.forProcessed) {    return genFor(el, state)  } else if (el.if && !el.ifProcessed) {    return genIf(el, state)  } else if (el.tag === 'template' && !el.slotTarget && !state.pre) {    return genChildren(el, state) || 'void 0'  } else if (el.tag === 'slot') {    return genSlot(el, state)  } else {    // component or element    let code    if (el.component) {      code = genComponent(el.component, el, state)    } else {      let data      if (!el.plain || (el.pre && state.maybeComponent(el))) {        data = genData(el, state)      }      const children = el.inlineTemplate ? null : genChildren(el, state, true)      code = `_c('${el.tag}'${        data ? `,${data}` : '' // data      }${        children ? `,${children}` : '' // children      })`    }    // module transforms    for (let i = 0; i < state.transforms.length; i++) {      code = state.transforms[i](el, code)    }    return code  }}

接下来依次看看genForgenIf的函数源码:

export function genFor (el, state , altGen, altHelper) {  const exp = el.for  const alias = el.alias  const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''  const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''  el.forProcessed = true // avoid recursion  return `${altHelper || '_l'}((${exp}),` +     `function(${alias}${iterator1}${iterator2}){` +      `return ${(altGen || genElement)(el, state)}` + //递归调用genElement    '})'}

在我们的例子里,当他处理liast树时,会先调用genElement,处理到for属性时,此时forProcessed为虚值,此时调用genFor处理li树中的v-for相关的属性。然后再调用genElement处理li树,此时因为forProcessedgenFor中已被标记为true。因此genFor不会被执行,继而执行genIf处理与v-if相关的属性。

export function genIf (el,state,altGen,altEmpty) {  el.ifProcessed = true // avoid recursion  // 调用genIfConditions主要处理el.ifConditions属性  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)}function genIfConditions (conditions, state, altGen, altEmpty) {  if (!conditions.length) {    return altEmpty || '_e()' // _e用于生成空VNode  }  const condition = conditions.shift()  if (condition.exp) { //condition.exp即v-if绑定值,例子中则为'index!==0'    // 生成一段带三目运算符的js代码字符串    return `(${condition.exp})?${       genTernaryExp(condition.block)    }:${      genIfConditions(conditions, state, altGen, altEmpty)    }`  } else {    return `${genTernaryExp(condition.block)}`  }  // v-if with v-once should generate code like (a)?_m(0):_m(1)  function genTernaryExp (el) {    return altGen      ? altGen(el, state)      : el.once        ? genOnce(el, state)        : genElement(el, state)  }}

参考 前端进阶面试题详细解答

最后,经过codegen生成的js代码如下:

function render() {  with(this) {    return _c('ul', _l((items), function (item, index) {      return (index !== 0) ? _c('li') : _e()    }), 0)  }}

其中:

“vue中v-for比v-if高的原因是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯