跳至主要內容

vue2和vue3的v-if与v-for的优先级差异

Mr.Chen开发笔记Vue大约 1 分钟约 409 字

最近在使用vue3写一个公共表格组件,操作列需要利用v-if判断是否渲染这个操作按钮。居然提示:属性 button 此时没有在该实例上定义。这是原本的代码:

<template slot-scope="scope">
   <template v-if="item.showConfig.type=== 'button'">
      <el-button class="table-opt-button" 
                 plain 
                 v-for="(button, index) in item.showConfig.buttons" 
                 :key="index + button.title"
                 :title="button.title" 
                 @click="button.func(scope.row)" 
                 v-if="button.show ? button.show(scope.row, button.buttonCode) : true">
                  <i :class="button.icon"></i>
      </el-button>
  </template>
</template>

查了vue2vue3的文档发现了一个问题:

  • Vue2:当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

这样写在vue2是完全正确的,官方也是这样写的。

  • Vue3:当它们同时存在于一个节点上时,v-ifv-for 的优先级更高。这意味着 v-if 的条件将无法访问到 v-for 作用域内定义的变量别名:
	<!--
 这会抛出一个错误,因为属性 todo 此时
 没有在该实例上定义
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo.name }}
</li>

很明显vue3vue2的表现有差异,这就是导致问题的原因。

那么在vue3中,这种问题怎么处理呢?

在外新包装一层 <template> 再在其上使用 v-for 可以解决这个问题:

<template v-for="todo in todos">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>
上次编辑于: