一、条件渲染
1.1 v-if 指令
语法:
<div v-if="表达式">内容</div> <div v-else-if="表达式">内容</div> <div v-else>内容</div>
特点:
-
基于条件判断是否创建或移除DOM元素
-
切换频率较低的场景使用
-
v-if、v-else-if、v-else必须连续使用,中间不能被打断
示例:
<div id="root">
<div v-if="type === 'A'">显示A</div>
<div v-else-if="type === 'B'">显示B</div>
<div v-else>显示其他</div>
</div>
1.2 v-show 指令
语法:
<div v-show="表达式">内容</div>
特点:
-
通过CSS的
display: none控制显示/隐藏 -
DOM元素始终存在,只是视觉上隐藏
-
切换频率高的场景使用
-
初始渲染开销大,切换开销小
1.3 v-if vs v-show 对比
| 特性 | v-if | v-show |
|---|---|---|
| DOM操作 | 添加/删除DOM节点 | 切换CSS的display属性 |
| 初始渲染 | 条件为false时不渲染 | 无论条件都渲染,然后隐藏 |
| 切换开销 | 高(需要重建DOM) | 低(只修改CSS) |
| 适用场景 | 不频繁切换的场景 | 频繁切换的场景 |
| 性能影响 | 减少初始DOM节点数量 | 增加初始DOM节点数量 |
1.4 template 标签的使用
<template v-if="n === 1">
<h1>标题1</h1>
<p>段落1</p>
<span>内容1</span>
</template>
特点:
-
作为不可见的包裹元素,不会在最终HTML中显示
-
只能与
v-if、v-else-if、v-else、v-for配合使用 -
不能与
v-show一起使用
二、列表渲染
2.1 v-for 指令基础
语法:
<li v-for="(item, index) in items" :key="item.id">
{{ item.name }} - 索引: {{ index }}
</li>
可遍历的数据结构:
-
遍历数组(最常用):
<ul>
<li v-for="(person, index) in persons" :key="person.id">
{{ index }} - {{ person.name }} ({{ person.age }})
</li>
</ul>
-
遍历对象:
<ul>
<li v-for="(value, key, index) in car" :key="key">
{{ index }} - {{ key }}: {{ value }}
</li>
</ul>
-
遍历字符串(很少用):
<span v-for="(char, index) in 'hello'" :key="index">
{{ char }}
</span>
-
遍历数字(很少用):
<span v-for="n in 5" :key="n">{{ n }}</span>
<!-- 输出:1 2 3 4 5 -->
2.2 :key 的重要性
为什么需要key?
key是Vue识别节点的标识,用于高效的DOM更新。
key的内部原理(虚拟DOM Diff算法)
数据更新流程:
数据变化 → 响应式系统检测 → 重新生成虚拟DOM → 新旧虚拟DOM差异对比 → 最小化更新真实DOM
Diff算法对比规则:
-
找到相同key:
-
内容未变 → 复用之前的真实DOM
-
内容变化 → 生成新真实DOM,替换旧DOM
-
-
未找到相同key:
-
创建新真实DOM,添加到页面
-
key的选择策略
推荐使用:
-
数据的唯一标识:id、手机号、身份证号等
<li v-for="person in persons" :key="person.id">
{{ person.name }}
</li>
谨慎使用index作为key:
<!-- 可能引发问题的场景 -->
<li v-for="(person, index) in persons" :key="index">
{{ person.name }}
</li>
index作为key的问题:
-
效率问题:逆序添加/删除时,产生不必要的真实DOM更新
-
数据错乱:包含输入类DOM时,可能产生错误的DOM更新
何时可以使用index:
-
仅用于展示的静态列表
-
没有逆序操作
-
没有输入类表单元素
三、综合应用
3.1 列表过滤与排序
<div id="app">
<!-- 搜索功能 -->
<input type="text" v-model="keyword" placeholder="搜索姓名">
<!-- 排序按钮 -->
<button @click="sortType = 1">年龄升序 ↑</button>
<button @click="sortType = 2">年龄降序 ↓</button>
<button @click="sortType = 0">原顺序</button>
<!-- 列表渲染 -->
<ul>
<li v-for="p in filteredPersons" :key="p.id">
{{ p.id }} - {{ p.name }} ({{ p.age }}岁)
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
keyword: '',
sortType: 0, // 0:原顺序, 1:升序, 2:降序
persons: [
{ id: '001', name: '张三', age: 25 },
{ id: '002', name: '李四', age: 22 },
{ id: '003', name: '王五', age: 28 },
{ id: '004', name: '赵六', age: 20 }
]
},
computed: {
filteredPersons() {
let arr = this.persons
// 1. 过滤(根据关键字)
if (this.keyword) {
arr = arr.filter(person =>
person.name.includes(this.keyword)
)
}
// 2. 排序
if (this.sortType === 1) {
arr = [...arr].sort((a, b) => a.age - b.age) // 升序
} else if (this.sortType === 2) {
arr = [...arr].sort((a, b) => b.age - a.age) // 降序
}
return arr
}
}
})
</script>
3.2 数组排序方法详解
sort()方法比较函数:
arr.sort((a, b) => {
// 返回值 < 0: a排在b前面
// 返回值 > 0: b排在a前面
// 返回值 = 0: 保持原顺序
})
// 数字排序口诀:前减后得升序,后减前得降序
numbers.sort((a, b) => a - b) // 升序
numbers.sort((a, b) => b - a) // 降序
3.3 条件渲染与列表渲染结合
<div id="app">
<!-- 根据数据是否为空显示不同内容 -->
<div v-if="items.length === 0">
<p>暂无数据</p>
<button @click="loadData">加载数据</button>
</div>
<template v-else>
<h3>数据列表 (共{{ items.length }}条)</h3>
<ul>
<li v-for="item in items" :key="item.id">
<span v-if="item.isNew" class="new-badge">NEW</span>
{{ item.title }}
<span v-show="item.hot">热</span>
</li>
</ul>
</template>
</div>
四、实践与注意事项
4.1 性能优化
-
合理使用v-if和v-show
-
初始不需要显示 → 使用
v-if -
需要频繁切换 → 使用
v-show
-
-
避免v-if和v-for同时用在同一个元素
<!-- 不推荐 --> <li v-for="user in users" v-if="user.isActive"> {{ user.name }} </li> <!-- 推荐:使用计算属性过滤 --> <li v-for="user in activeUsers" :key="user.id"> {{ user.name }} </li> -
为v-for始终添加key
-
使用唯一标识,避免使用index
-
4.2 常见问题解决
问题1:列表更新视图不刷新
-
确保使用Vue的响应式方法修改数组
// 正确 this.items.push(newItem) this.items.splice(index, 1, newItem) Vue.set(this.items, index, newValue) // 错误(不会触发视图更新) this.items[index] = newValue this.items.length = 0
问题2:嵌套循环的key
<div v-for="category in categories" :key="category.id">
<h3>{{ category.name }}</h3>
<div v-for="product in category.products"
:key="product.id">
{{ product.name }}
</div>
</div>
4.3 响应式原理回顾
Vue的响应式系统工作流程:
-
数据被Object.defineProperty()代理
-
数据变化触发setter
-
通知所有依赖的Watcher
-
Watcher调用更新函数
-
重新生成虚拟DOM
-
执行Diff算法对比新旧虚拟DOM
-
最小化更新真实DOM
虚拟DOM的优势:
-
减少直接操作DOM的次数
-
批量更新,提高性能
-
跨平台能力(可渲染到不同平台)
总结
| 特性 | 条件渲染 | 列表渲染 |
|---|---|---|
| 主要指令 | v-if, v-else-if, v-else, v-show | v-for |
| 核心概念 | 条件判断显示/隐藏 | 数据遍历 |
| 性能关键 | 合理选择v-if/v-show | 正确使用:key |
| 常用场景 | 模态框、选项卡、权限控制 | 数据列表、表格、菜单 |
888

被折叠的 条评论
为什么被折叠?



