v-if和v-for的优先级

v-if和v-for是开发中经常会遇到的2个指令,那么在使用的过程中,2者如果同时存在同一个标签上,谁的优先级会更高一点呢?

那么我们从源码的角度去看他
源码位置compiler/codegen/index.js

genElement方法中,我们可以看到一些if else的判断

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

处理for循环是处于if的上面的,所以我们由此可以判定v-for的优先级是高于v-if的。

那么我们写个demo,在一个p标签上,同时加上v-for和v-if:

{{item}}

当我们打印vue.$options.render,打印出的函数,我们可以在浏览器中看到一个打印出来的render函数

ƒ anonymous() {
  with(this){return _c('div',{attrs:{"id":"demo"}},[_c('h1',[_v("vue中v-if和v-for谁的优先级更高?应该如何正确使用以避免性能问题?")]),_v(" "),
  _l((arr),function(item){return (isTrue)?_c('p'):_e()})],2)}

}

我们可以看到,在这里的_l就是vue中的列表渲染函数,他在执行的时候,是先执行的for循环,在每次循环的时候,去return一个isTrue

那我们在写一个demo,同一个标签上不出现v-for和v-if:


同样,我们执行上述的打印操作,浏览器中会打印出下面这个函数

ƒ anonymous() {
  with(this){return _c('div',{attrs:{"id":"demo"}},[_c('h1',[_v("vue中v-if和v-for谁的优先级更高?应该如何正确使用以避免性能问题?")]),_v(" "),
  (isTrue)?_l((arr),function(item){return _c('p')}):_e()],2)}
}

从第二行代码我们可以看到,vue先执行了一个isTrue是否存在的判断,再进行了_l函数的for循环执行。

所以我们可以得出结论,v-for的优先级是高于v-if的,如果两者同时出现的话,那每次循环都会执行v-if,会很浪费性能,我们正确的做法应该是再v-for的外面新增一个模板标签template,在template上使用v-if

我们经常会遇见这种情况,在v-for的时候,在数组中会有一些需要进行v-if的判断,这种情况下,我们如果先使用computed将不需要渲染的项过滤出来,那么在进行v-for的时候,循环的就只是需要渲染的项,这也是提升vue性能的一种方式。

你可能感兴趣的:(v-if和v-for的优先级)