04Vue.js 条件渲染与列表渲染

一、条件渲染

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-ifv-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-ifv-else-ifv-elsev-for配合使用

  • 不能v-show一起使用

二、列表渲染

2.1 v-for 指令基础

语法

<li v-for="(item, index) in items" :key="item.id">
    {{ item.name }} - 索引: {{ index }}
</li>

可遍历的数据结构

  1. 遍历数组(最常用):

<ul>
    <li v-for="(person, index) in persons" :key="person.id">
        {{ index }} - {{ person.name }} ({{ person.age }})
    </li>
</ul>
  1. 遍历对象

<ul>
    <li v-for="(value, key, index) in car" :key="key">
        {{ index }} - {{ key }}: {{ value }}
    </li>
</ul>
  1. 遍历字符串(很少用):

<span v-for="(char, index) in 'hello'" :key="index">
    {{ char }}
</span>
  1. 遍历数字(很少用):

<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算法对比规则

  1. 找到相同key

    • 内容未变 → 复用之前的真实DOM

    • 内容变化 → 生成新真实DOM,替换旧DOM

  2. 未找到相同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的问题

  1. 效率问题:逆序添加/删除时,产生不必要的真实DOM更新

  2. 数据错乱:包含输入类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 性能优化

  1. 合理使用v-if和v-show

    • 初始不需要显示 → 使用v-if

    • 需要频繁切换 → 使用v-show

  2. 避免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>
  3. 为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的响应式系统工作流程

  1. 数据被Object.defineProperty()代理

  2. 数据变化触发setter

  3. 通知所有依赖的Watcher

  4. Watcher调用更新函数

  5. 重新生成虚拟DOM

  6. 执行Diff算法对比新旧虚拟DOM

  7. 最小化更新真实DOM

虚拟DOM的优势

  • 减少直接操作DOM的次数

  • 批量更新,提高性能

  • 跨平台能力(可渲染到不同平台)


总结

特性条件渲染列表渲染
主要指令v-if, v-else-if, v-else, v-showv-for
核心概念条件判断显示/隐藏数据遍历
性能关键合理选择v-if/v-show正确使用:key
常用场景模态框、选项卡、权限控制数据列表、表格、菜单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值