v-for 是 Vue.js 中用于循环渲染列表的核心指令,功能类似 JavaScript 的 for...of 循环。

以下是详细用法解析:

1. 基础语法 ★★★

<!-- 遍历数组items -->
<li v-for="(item, index) in items" :key="item.id">
  {{ index }} - {{ item.name }}
</li>

<!-- 遍历对象object -->
<div v-for="(value, key, index) in object" :key="key">
  {{ index }}. {{ key }}: {{ value }}
</div>
参数 说明 数组示例 对象示例
第一参数 当前项的值 item value
第二参数 索引(遍历数组时)/键名(遍历对象时) index(数字) key(字符串)
第三参数 仅遍历对象时可用,遍历索引 - index(数字)

2. 必须的 :key 属性

Vue 要求为每个 v-for 项添加唯一 key,用于虚拟 DOM 高效更新:

<!-- 推荐用唯一ID -->
<div v-for="user in users" :key="user.id"></div>

<!-- 仅测试环境可用索引(不推荐生产环境) -->
<div v-for="(item, index) in items" :key="index"></div>

为什么需要 key?

  • 帮助 Vue 识别节点身份
  • 避免列表重新渲染时的性能问题
  • 维持组件内部状态(如输入框内容)

3. 常见数据源类型

遍历数组

data() {
  return {
    fruits: ['Apple', 'Banana', 'Orange']
  }
}
<ul>
  <li v-for="fruit in fruits" :key="fruit">{{ fruit }}</li>
</ul>

遍历对象

data() {
  return {
    person: {
      name: 'Alice',
      age: 25,
      job: 'Developer'
    }
  }
}
<ul>
  <li v-for="(value, key) in person" :key="key">
    {{ key }}: {{ value }}
  </li>
</ul>

遍历数字范围

<span v-for="n in 5" :key="n">{{ n }}</span>
<!-- 输出:1 2 3 4 5 -->

4. 高级用法

v-if 结合

<!-- 不推荐!v-for 和 v-if 同时作用于同一元素 -->
<li v-for="todo in todos" v-if="!todo.isComplete" :key="todo.id">
  {{ todo.text }}
</li>

<!-- 推荐方案:使用计算属性过滤 -->
<li v-for="todo in incompleteTodos" :key="todo.id">
  {{ todo.text }}
</li>
computed: {
  incompleteTodos() {
    return this.todos.filter(todo => !todo.isComplete);
  }
}

嵌套循环

<ul v-for="category in categories" :key="category.id">
  <li>{{ category.name }}</li>
  <ul>
    <li v-for="product in category.products" :key="product.id">
      {{ product.name }}
    </li>
  </ul>
</ul>

5. 性能优化技巧

  1. 避免同时使用 v-forv-if
    Vue 会优先执行 v-for,导致不必要的计算

  2. 大数据量使用虚拟滚动
    集成库如 vue-virtual-scroller

    <RecycleScroller :items="bigList" :item-size="50">
      <template v-slot="{ item }">
        <div>{{ item.content }}</div>
      </template>
    </RecycleScroller>
  3. 对象变化检测限制
    Vue 无法自动检测对象属性的添加/删除,需用 Vue.set() 或展开新对象:

    // 错误!不会触发更新
    this.obj.newProp = 'value';
    
    // 正确
    this.obj = { ...this.obj, newProp: 'value' };

6. 与其他框架对比

功能 Vue (v-for) React Angular
语法 v-for="item in items" items.map() *ngFor="let item of items"
key 要求 必须 必须 必须
索引获取 (item, index) array.map((item, index) (item, index)
对象遍历 支持 Object.entries 不支持

7. 常见问题

Q:为什么列表更新后视图不刷新?

A:可能原因:

  • 数组使用了非变更方法(如 filter 未重新赋值)
  • 对象属性直接修改未触发响应
  • key 值不唯一或重复

解决方案

// 数组
this.items = this.items.filter(x => x.isActive);

// 对象
this.obj = { ...this.obj, newProp: 123 };

Q:如何实现列表动画?

<transition-group name="fade" tag="ul">
  <li v-for="item in items" :key="item.id">
    {{ item.text }}
  </li>
</transition-group>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}

掌握 v-for 的合理使用是 Vue 开发的基础,注意结合 key 的使用和性能优化策略,可以构建高效动态的列表界面。