前端八股Vue(6)---v-if和v-for

目录

  • [一、v-for 详解](#一、v-for 详解)
  • [1.1 作用](#1.1 作用)
  • [1.2 语法](#1.2 语法)
  • [1.3 要点](#1.3 要点)
  • [二、v-if 详解](#二、v-if 详解)
  • [2.1 作用](#2.1 作用)
  • [2.2 语法](#2.2 语法)
  • [2.3 v-if vs v-show](#2.3 v-if vs v-show)
  • [三、高频面试坑点:v-for 和 v-if 不能用在同一个标签上](#三、高频面试坑点:v-for 和 v-if 不能用在同一个标签上)
  • [3.1 错误示例](#3.1 错误示例)
  • [3.2 原因](#3.2 原因)
  • [3.3 正确写法](#3.3 正确写法)
  • [四、v-for 里面的 key 作用](#四、v-for 里面的 key 作用)
  • [4.1 一句话核心答案](#4.1 一句话核心答案)
  • [4.2 详细解释](#4.2 详细解释)
  • [4.3 图解:有 key vs 无 key](#4.3 图解:有 key vs 无 key)
  • [4.4 为什么不能用 index 做 key?(高频考点)](#4.4 为什么不能用 index 做 key?(高频考点))
  • 五、面试标准满分回答
  • [Q1:v-for 和 v-if 为什么不能一起用?](#Q1:v-for 和 v-if 为什么不能一起用?)
  • [Q2:v-for 中的 key 有什么作用?为什么不能用 index?](#Q2:v-for 中的 key 有什么作用?为什么不能用 index?)
  • 六、总结对比表

一、v-for 详解

1.1 作用

v-for 是循环指令,用于遍历数组或对象渲染列表,必须绑定 key 提升性能。

1.2 语法

javascript 复制代码
<template>
  <!-- 遍历数组 -->
  <div v-for="(item, index) in list" :key="index">
    {{ item }}
  </div>
  
  <!-- 遍历对象 -->
  <div v-for="(value, key, index) in obj" :key="key">
    {{ key }}: {{ value }}
  </div>
  
  <!-- 遍历数字(1-10) -->
  <div v-for="n in 10" :key="n">{{ n }}</div>
  
  <!-- 遍历字符串 -->
  <div v-for="char in 'hello'" :key="char">{{ char }}</div>
</template>

1.3 要点

要点 说明
必须绑定 key 提高 Vue 复用 DOM、diff 效率
可遍历类型 数组、对象、数字、字符串
参数顺序 数组:(item, index);对象:(value, key, index)

二、v-if 详解

2.1 作用

v-if 是条件渲染指令,根据表达式真假创建或销毁 DOM。

2.2 语法

javascript 复制代码
<template>
  <!-- 单独使用 -->
  <div v-if="isShow">显示</div>
  
  <!-- v-else -->
  <div v-if="isLogin">欢迎回来</div>
  <div v-else>请先登录</div>
  
  <!-- v-else-if -->
  <div v-if="status === 'success'">成功</div>
  <div v-else-if="status === 'loading'">加载中</div>
  <div v-else>失败</div>
  
  <!-- 支持 template 批量渲染 -->
  <template v-if="isShow">
    <h2>标题</h2>
    <p>内容</p>
  </template>
</template>

2.3 v-if vs v-show

对比 v-if v-show
控制方式 创建/销毁 DOM 切换 display: none
DOM 存在性 假时不存在 始终存在
切换开销
初始开销 低(假时不渲染) 高(总是渲染)
支持 template
支持 v-else
适用场景 很少切换 频繁切换

三、高频面试坑点:v-for 和 v-if 不能用在同一个标签上

3.1 错误示例

javascript 复制代码
<!-- ❌ 不推荐!!! -->
<div v-for="item in list" v-if="item.isActive" :key="item.id">
  {{ item.name }}
</div>

3.2 原因

v-for 优先级比 v-if 高,会先循环全部项,再逐个判断 v-if,造成性能浪费:

javascript 复制代码
// 本质执行逻辑(简化)
// 即使只有 1 项符合条件,也要遍历全部 1000 条数据
list.forEach(item => {
  if (item.isActive) {
    // 渲染 DOM
  }
})

3.3 正确写法

javascript 复制代码
<!-- ✅ 方式1:在外层套 <template> -->
<template v-for="item in list" :key="item.id">
  <div v-if="item.isActive">
    {{ item.name }}
  </div>
</template>

<!-- ✅ 方式2:提前在 computed 里过滤好数组 -->
<template>
  <div v-for="item in activeList" :key="item.id">
    {{ item.name }}
  </div>
</template>

<script setup>
import { computed } from 'vue'

const list = ref([...])

const activeList = computed(() => 
  list.value.filter(item => item.isActive)
)
</script>

<!-- ✅ 方式3:v-show 替代(如果只是隐藏) -->
<div v-for="item in list" v-show="item.isActive" :key="item.id">
  {{ item.name }}
</div>

四、v-for 里面的 key 作用

4.1 一句话核心答案

key 是 Vue 用来识别每个虚拟 DOM 节点的唯一标识,方便 Vue 在列表更新时做高效的 DIFF 对比,实现 DOM 复用和精准更新,提升渲染性能。

4.2 详细解释

作用 说明
标识唯一性 key 给每个列表项一个唯一 ID,让 Vue 知道谁是谁
提高 diff 效率 有 key:Vue 能精准找到变化项,只更新该 DOM;无 key:Vue 只能暴力复用、顺序对比
避免渲染错乱 删除、逆序、插入时,没有 key 容易出现复选框错位、过渡动画混乱

4.3 图解:有 key vs 无 key

复制代码
无 key(索引对比):
原列表:A B C D
新列表:A C D

Vue 对比:
位置0: A → A ✅ 复用
位置1: B → C ❌ 更新(但 B 应该是删除)
位置2: C → D ❌ 更新
位置3: D → 无 ❌ 删除
结果:2 次更新 + 1 次删除

有 key(id 对比):
原列表:A(id:1) B(id:2) C(id:3) D(id:4)
新列表:A(id:1) C(id:3) D(id:4)

Vue 对比:
id:1 存在 ✅ 复用
id:2 不存在 ❌ 删除
id:3 存在 ✅ 复用
id:4 存在 ✅ 复用
结果:1 次删除,0 次更新

4.4 为什么不能用 index 做 key?(高频考点)

javascript 复制代码
<!-- ❌ 错误:用 index 做 key -->
<div v-for="(item, index) in list" :key="index">
  {{ item.name }}
  <input type="checkbox" />
</div>

问题:

操作 用 index 作为 key 的问题
列表逆序 index 变化,所有 key 都变了,Vue 会重新创建所有 DOM
删除/插入 后续项的 index 改变,导致 DOM 复用错误
表单错位 input 框的内容会错位,因为 key 变了
性能 大量不必要的 DOM 更新,性能反而更差

正确做法:

javascript 复制代码
<!-- ✅ 正确:用后端返回的唯一 id -->
<div v-for="item in list" :key="item.id">
  {{ item.name }}
</div>

<!-- ✅ 数据没有 id 时,可以用 Symbol 或自定义唯一标识 -->
<div v-for="(item, index) in list" :key="`item-${item.name}-${item.age}`">
  {{ item.name }}
</div>

五、面试标准满分回答

Q1:v-for 和 v-if 为什么不能一起用?

答: 因为 v-for 的优先级高于 v-if,如果写在同一个标签上,Vue 会先执行循环遍历所有数据,再对每一项进行条件判断。这样即使大部分数据都不需要渲染,也会先遍历一遍,造成性能浪费。正确的做法是用 computed 先过滤数据,或者在 <template> 外层包一层。

Q2:v-for 中的 key 有什么作用?为什么不能用 index?

答: key 是 Vue 虚拟 DOM diff 算法中识别节点的唯一标识。有 key 时,Vue 能精准定位变化项,只更新必要的 DOM;没有 key 时,Vue 只能按顺序对比,容易造成错误渲染和性能问题。

不能用 index 作为 key,因为当列表发生逆序、删除、插入等操作时,index 会变化,导致 Vue 认为所有节点都变了,从而无法复用 DOM,反而降低性能,还可能导致表单状态错位。应该使用后端返回的唯一 id 作为 key。


六、总结对比表

指令 作用 优先级 必须配合 注意事项
v-for 循环渲染 :key 不要和 v-if 同标签
v-if 条件渲染 v-else-if/v-else 切换开销大
key 节点标识 - 配合 v-for 不要用 index
相关推荐
程序员buddha2 小时前
ES6 迭代器与生成器
前端·javascript·es6
周周记笔记2 小时前
初识HTML和CSS(一)
前端·css·html
aq55356002 小时前
网页开发四剑客:HTML/CSS/JS/PHP全解析
javascript·css·html
程序员buddha2 小时前
TypeScript详细教程
javascript·ubuntu·typescript
chxii3 小时前
在 IIS 中实现 SSL 证书的自动续期
前端
周星星日记3 小时前
vue3中静态提升和patchflag实现
前端·vue.js·面试
橘子编程3 小时前
React 19 全栈开发实战指南
前端·react.js·前端框架
DanCheOo3 小时前
AI Streaming 架构:从浏览器到服务端的全链路流式设计
前端·agent
我是小趴菜3 小时前
前端如何让图片、视频、pdf等文件在浏览器直接下载而非预览
前端