本篇内容介绍了“vue中v-for比v-if高的原因是什么”的有关知识,免费云主机域名在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 以下面的例子出发分析:
newVue({ el:'#app', template:`
- {{item}}
`
})从上篇文章可以知道,编译有三个步骤parse : 解析模板字符串生成 AST语法树optimize : 优化语法树,主要时标记静态节点,提高更新页面的性能codegen : 生成js代码,主要是render函数和staticRenderFns函数我们再次顺着这三个步骤对上述例子进行分析。parse过程中,会对模板使用大量的正则表达式去进行解析。开头的例子会被解析成以下AST
节点:
//其实ast有很多属性,我这里只展示涉及到分析的属性 ast={ 'type':1, 'tag':'ul', 'attrsList':[], attrsMap:{}, 'children':[{ 'type':1, 'tag':'li', 'attrsList':[], 'attrsMap':{ 'v-for':'(item,index)indata', '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
指令,除了记录在attrsMap
和attrsList
,还会新增for
(对应要遍历的对象或数组),alias
,iterator1
,iterator2
对应v-for
指令绑定内容中的第一,第二,第三个参数,开头的例子没有第三个参数,因此没有iterator2
属性。对于v-if
指令,把v-if
指令中绑定的内容取出放在if
中,与此同时初始化ifConditions
属性为数组,然后往里面存放对象:{exp,block}
,其中exp
存放v-if
指令中绑定的内容,block
指向el
。optimize 过程在此不做分析,因为本例子没有静态节点。上一篇文章从const code = generate(ast, options)
开始分析过其生成代码的过程,generate
内部会调用genElement
用来解析el
,也就是AST
语法树。我们来看一下genElement
的源码:
exportfunctiongenElement(el:ASTElement,state:CodegenState):string{ if(el.parent){ el.pre=el.pre||el.parent.pre } if(el.staticRoot&&!el.staticProcessed){ returngenStatic(el,state) }elseif(el.once&&!el.onceProcessed){ returngenOnce(el,state) //其实从此处可以初步知道为什么v-for优先级比v-if高, //因为解析ast树生成渲染函数代码时,会先解析ast树中涉及到v-for的属性 //然后再解析ast树中涉及到v-if的属性 //而且genFor在会把el.forProcessed置为true,防止重复解析v-for相关属性 }elseif(el.for&&!el.forProcessed){ returngenFor(el,state) }elseif(el.if&&!el.ifProcessed){ returngenIf(el,state) }elseif(el.tag==='template'&&!el.slotTarget&&!state.pre){ returngenChildren(el,state)||'void0' }elseif(el.tag==='slot'){ returngenSlot(el,state) }else{ //componentorelement letcode if(el.component){ code=genComponent(el.component,el,state) }else{ letdata if(!el.plain||(el.pre&&state.maybeComponent(el))){ data=genData(el,state) } constchildren=el.inlineTemplate?null:genChildren(el,state,true) code=`_c('${el.tag}'${data?`,${data}`:''//data}${children?`,${children}`:''//children})` } //moduletransforms for(leti=0;i
接下来依次看看genFor
和genIf
的函数源码:
exportfunctiongenFor(el,state,altGen,altHelper){ constexp=el.for constalias=el.alias constiterator1=el.iterator1?`,${el.iterator1}`:'' constiterator2=el.iterator2?`,${el.iterator2}`:'' el.forProcessed=true//avoidrecursion return`${altHelper||'_l'}((${exp}),`+ `function(${alias}${iterator1}${iterator2}){`+ `return${(altGen||genElement)(el,state)}`+//递归调用genElement '})' }
在我们的例子里,当他处理li
的ast
树时,会先调用genElement
,处理到for
属性时,此时forProcessed
为虚值,此时调用genFor
处理li
树中的v-for
相关的属性。然后再调用genElement
处理li
树,此时因为forProcessed
在genFor
中已被标记为true
。因此genFor
不会被执行,继而执行genIf
处理与v-if
相关的属性。
exportfunctiongenIf(el,state,altGen,altEmpty){ el.ifProcessed=true//avoidrecursion //调用genIfConditions主要处理el.ifConditions属性 returngenIfConditions(el.ifConditions.slice(),state,altGen,altEmpty) } functiongenIfConditions(conditions,state,altGen,altEmpty){ if(!conditions.length){ returnaltEmpty||'_e()'//_e用于生成空VNode } constcondition=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-ifwithv-onceshouldgeneratecodelike(a)?_m(0):_m(1) functiongenTernaryExp(el){ returnaltGen ?altGen(el,state) :el.once ?genOnce(el,state) :genElement(el,state) } }
参考 前端进阶面试题详细解答最后,经过codegen生成的js代码如下:
functionrender(){ with(this){ return_c('ul',_l((items),function(item,index){ return(index!==0)?_c('li'):_e() }),0) } }
其中:_c
: 调用 createElement
去创建 VNode
_l
: renderList
函数,主要用来渲染列表_e
: createEmptyVNode
函数,主要用来创建空VNode
“vue中v-for比v-if高的原因是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注百云主机网站,小编将为大家输出更多高质量的实用文章!
这篇文章主要讲解了“Python中单例模式如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中单例模式如何实现”吧!单例 — 让 类 创建的对象,在系统中 只有唯一的一个实例;1)、定义一个类属…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。