1、源码解析

当v-for 和 v-if在同一级使用时,系统会报错This 'v-if' should be moved to the wrapper element,因为当它们处于同一节点,v-for的优先级比v-if更高。这种情况时,for循环还是会走下去。下面我们先从渲染函数再到源码进行分析:

const VueTemplateCompiler = require('vue-template-compiler')

const template = '<div v-for="item in 3" :key="item" v-if="false">{{ item }}</div>'

// 模版编译成render方法
const compile = VueTemplateCompiler.compile(template)

console.log(compile.render)

with (this) { return _l((3), function (item) { return (false) ? _c('div', { key: item }, [_v(_s(item))]) : _e() }) }

从渲染函数可以看出先进行for循环再在其内部进行条件判断,这明显是不符合性能优化的;我们再来看看源码的实现:在vue/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) { // v-for
    return genFor(el, state)
  } else if (el.if && !el.ifProcessed) { // v-if
    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
  }
}

可以看出,在解析时先解析v-for再解析v-if

2、解决方案

1、当不满足条件时跳过循环的执行,那么可以将 v-if 置于v-for的外层元素(可见报错提示信息:This 'v-if' should be moved to the wrapper element)

2、 如果条件出现在循环内部,则可通过计算属性对数据源fliter进行操作过滤掉不满足条件的数据(可见报错提示信息:'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if')。

Logo

前往低代码交流专区

更多推荐