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


本篇内容介绍了“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指令,除了记录在attrsMapattrsList,还会新增for(对应要遍历的对象或数组),aliasiterator1,iterator2对应v-for指令绑定内容中的第一,第二,第三个参数,开头的例子没有第三个参数,因此没有iterator2属性。对于v-if指令,把v-if指令中绑定的内容取出放在if中,与此同时初始化ifConditions属性为数组,然后往里面存放对象:{exp,block},其中exp存放v-if指令中绑定的内容,block指向eloptimize 过程在此不做分析,因为本例子没有静态节点。上一篇文章从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

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

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
'})'
}

在我们的例子里,当他处理liast树时,会先调用genElement,处理到for属性时,此时forProcessed为虚值,此时调用genFor处理li树中的v-for相关的属性。然后再调用genElement处理li树,此时因为forProcessedgenFor中已被标记为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中单例模式如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中单例模式如何实现”吧!单例 — 让 类 创建的对象,在系统中 只有唯一的一个实例;1)、定义一个类属…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 05/22 09:01
Next 05/22 09:01

相关推荐