Vue3---条件渲染-与-列表循环渲染

273 阅读4分钟

#完整原文地址见简书www.jianshu.com/p/695bf35fa…



#本文内容提要

  • 条件渲染
    • v-ifv-show控制渲染的机制的区别
    • v-ifv-show各自的适用场景
    • v-ifv-else的配合 控制渲染
    • v-ifv-else-ifv-else的配合 控制渲染
  • 列表循环渲染
    • v-for例程(数组方式)

    • v-for例程(Object方式 --- 注意参数顺序!!!)

    • 注意使用Key值优化v-for的性能

    • 通过数组的变更函数 更新渲染列表UI

    • 通过 直接用新数组替换更新原数组 更新渲染列表UI

    • 通过改变 数组内容(元素) 更新渲染列表UI

    • 循环Object对象,增加Object对象内容,渲染更新UI

    • 使用v-for遍历一个数字

    • 特性“v-for的优先级高于v-if”,其引发的相关问题 及其 规避方法

      • 案例
      • 解决方案
      • 使用<template>UI占位符进行优化

###条件渲染 ####**`v-if`与`v-show`控制渲染的机制的区别** **当它们的参数值是`true`时,毫无疑问对应的组件便是展示的:** ``` Hello World! heheheheheheda
``` 效果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c6f714b126c546018c55d9bc18f4196d~tplv-k3u1fbpfcp-zoom-1.image) **当它们的参数值是`false`时, `v-if`通过 `直接暴力去除`对应DOM组件的形式 “隐藏”组件, 而`v-show`则通过`style="display: none;"`样式的配置 隐藏组件:** ``` ``` 效果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/59c58ed4da9e40b8afbd67070868edc7~tplv-k3u1fbpfcp-zoom-1.image)
#####`v-if`与`v-show`各自的适用场景 基于以上的隐藏组件的机制, 频率较低地隐藏组件的场景,两者都差不多, 不想占用过多DOM资源的话,可以考虑使用`v-if`; `v-show`适用于频率较高的隐藏组件的场景;
#####`v-if`与`v-else`的配合 控制渲染 上例程: ``` Hello World! heheheheheheda
``` **首先,注意`v-if`与`v-else`两个指令修饰的两个组件 一定要是成对出现的,放在一起前后两行衔接的, 不然容易出错或报错;
接着,`v-if`与`v-else`两个指令修饰的两个组件, 同一时间只会出现一个,
由`v-if`指定绑定的字段,`v-else`不需要指定; 字段为`true`时,`v-if`修饰的组件显示, 字段为`false`时,`v-else`修饰的组件显示:**![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/59164b52f6f54e0980dcf9a2c2564ecb~tplv-k3u1fbpfcp-zoom-1.image)![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/31d1f2a7d05d4470a532bccf39c80f31~tplv-k3u1fbpfcp-zoom-1.image)
####`v-if`、`v-else-if`与`v-else`的配合 控制渲染 **即如普通编程的逻辑, `v-if`绑定字段为true时候,只显示`v-if`修饰的组件, 否则, `v-else-if`绑定字段为true时候,只显示`v-else-if`修饰的组件, 再否则, 只显示`v-else`修饰的组件;** ``` ``` 效果图:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/58dbffb4f5e04c81a0e48a1e32d141c2~tplv-k3u1fbpfcp-zoom-1.image)
####列表循环渲染 **`v-for`例程(数组方式):** ``` Hello World! heheheheheheda
``` 效果图:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8265895d4a15449e99da43789f61001d~tplv-k3u1fbpfcp-zoom-1.image)
**`v-for`例程(Object方式 --- 注意参数顺序!!!):** ``` ``` 效果图:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a15261fda5c7414eb2af4e6308ce1eb2~tplv-k3u1fbpfcp-zoom-1.image)
####注意使用`Key值`优化`v-for`的性能 **当使用`v-for`做循环渲染,尽量加一个每一项都唯一的`Key值`, 这样下次新增元素的时候, `Vue底层`发现 其`Key值`在`数据更新前后`都没变的`DOM项`, 就会直接`复用`这个`DOM项`,而不用`重建`这个`DOM项`, 达到`优化性能`的目的;** ``` ```
####通过数组的变更函数 更新渲染列表UI **本质其实就是借助 [原生JS数组的 API](https://www.w3school.com.cn/jsref/jsref_obj_array.asp)对数据进行更新, 再借助`Vue`的`数据与UI`的`双向绑定特性`, 完成对UI的`更新渲染`:** ``` ``` **效果图如下, 这里由于功能比较繁多而简单,就不做详细操作了:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bbcd74a01f4b49a5a9936c2f7532b567~tplv-k3u1fbpfcp-zoom-1.image)**
####通过 直接用`新数组`替换更新`原数组` 更新渲染列表UI **借助数组API, 这里给出 `直接替换、拼接新数组、过滤关键词` 等三种案例, 如下代码注释:** ``` ```
####通过改变 数组内容(元素) 更新渲染列表UI ``` ``` ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5af921a53f8a4e938380e29698224589~tplv-k3u1fbpfcp-zoom-1.image)![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9e3f6dc2f46349af88b7131879507c62~tplv-k3u1fbpfcp-zoom-1.image)
####循环Object对象,增加Object对象内容,渲染更新UI ``` ``` **效果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ddb2eb26968f4d0b90494729ea25470e~tplv-k3u1fbpfcp-zoom-1.image)点击增加数据属性,更新UI:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cadcdff3055040b495f18a87c28e49fa~tplv-k3u1fbpfcp-zoom-1.image)**
####使用`v-for`遍历一个数字 关键代码:`
{{item}}
`: ``` ``` 效果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5e50e426caf14be3a696cf75fc86d6cd~tplv-k3u1fbpfcp-zoom-1.image)
####特性“`v-for`的优先级高于`v-if`”,其引发的相关问题 及其 规避方法 ``` ``` **如上代码, 我们编写了`v-if`,但其与`v-for`共存,则不起作用, 因`v-for`的优先级高于`v-if`:**![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c2b13b1e7b4c416887779d95c68c5cac~tplv-k3u1fbpfcp-zoom-1.image) **解决方案,分离`v-for`与`v-if`于不同的组件中:** ``` ``` 关键代码: ```
{{value}} --- {{key}}
``` 效果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c126859686954e538499cfb6deff24a2~tplv-k3u1fbpfcp-zoom-1.image) **但是有一个问题,这样会使得DOM层数增加:**![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a4a40a2e25094441b952db8e1fa43539~tplv-k3u1fbpfcp-zoom-1.image)

像这种本来只要一个<div>可以完成的事情,迫于特性无奈,要分成两个<div>的场景, 可以——使用<template>UI占位符进行优化, <template>标签位不占DOM位,只负责逻辑描述:

<script>
    const app = Vue.createApp({
        data() {
            return {
                listArray: ['Otoman', 'Wang', 'programmer'],
                listObject: {
                    firstName: 'Otoman',
                    lastName: 'wang',
                    job: 'programmer'
                }
            }
        },
        methods: {
            handleChangeBtnClick() {
                this.listObject.age = 100;
                this.listObject.sex = 'male';
            }
        },
        template: `
        <div>
            <template v-for="(value, key, index) in listObject" 
                :key="index"
            >
                <div v-if="key !== 'lastName'">
                    {{value}} --- {{key}}
                </div>
            </template>

            <div>
                <div v-for="item in 10">{{item}}</div>
                <button @click="handleChangeBtnClick">改变节点</button>
            </div>
        </div>`
    });

    const vm = app.mount('#heheApp');
</script>

关键代码:

            <template v-for="(value, key, index) in listObject" 
                :key="index"
            >
                <div v-if="key !== 'lastName'">
                    {{value}} --- {{key}}
                </div>
            </template>

效果如下,相较之前就少了一个层级: