Vue源码解析问题(1 v-if和v-for)

279 阅读1分钟

1. v-if和v-for那个优先级更高,如果同时出现,如何优化会得到更好的性能?

源码位置

url src\compiler\codegen\index.js

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)
  } else if (el.for && !el.forProcessed) { // 第64行 => for 优先级高于 if
    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 {
    // ...
  }
}

结论: 显然v-for优先于v-if被解析

测试 同级与不同级 比较 (如果同时出现,如何优化会得到更好的性能?)

<p v-for="item in items" v-if="condition"></p><!--  -->
<div v-if="condition"><p v-for="item in items"></p></div>

同级执行后

ƒ anonymous() {
  with(this){return _c('div',{attrs:{"id":"demo"}},_l((children),function(child){return (isFolder)?_c('p',[_v(_s(child.title))]):_e()}),0)}
}

不同级执行后

(function anonymous() {
  with (this) { return _c('div', { attrs: { "id": "demo" } }, [(isFolder) ? _c('div', _l((children), function (child) { return _c('p', [_v(_s(child.title))]) }), 0) : _e()]) }
})

发现渲染顺序 执行不同,得出结论

结论

  1. 解析渲染过程是先进入循环遍历数组,然后进行条件判断。
  2. 同时出现时,每次渲染都会先执行循环再判断条件,因为循环是不可避免的,并且浪费了性能,可以在外层进行v-if判断,在内部进行循环
  3. 如果条件出现循环内部,可通过计算属性提前过滤掉那些不需要显示的项