前端八股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
相关推荐
Alice-YUE32 分钟前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
是上好佳佳佳呀2 小时前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记
莎士比亚的文学花园2 小时前
Linux驱动开发(3)——设备树
开发语言·javascript·ecmascript
CDN3602 小时前
排查实录:网站偶发502/504错误?360CDN回源超时配置与日志分析技巧
前端·数据库
之歆3 小时前
Day07_CSS盒子模型 · 样式继承 · 用户代理样式
前端·css
01漫游者3 小时前
JavaScript函数与对象增强知识
开发语言·javascript·ecmascript
DanCheOo3 小时前
AI 应用的安全架构:Prompt 注入、数据泄露、权限边界
前端·人工智能·prompt·安全架构
We་ct4 小时前
深度剖析浏览器跨域问题
开发语言·前端·浏览器·跨域·cors·同源·浏览器跨域
weixin_427771614 小时前
前端调试隐藏元素
前端
threelab5 小时前
Three.js 代码云效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能