关于Vue2里 v-for和v-if一起用的时候会出现的问题

关于Vue2里 v-for和v-if一起用的时候会出现的问题

🎉🎉🎉欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!🙏🙏🙏

在这里插入图片描述

文章目录

  • 关于Vue2里 v-for和v-if一起用的时候会出现的问题
    • 1.介绍
    • 2.案例
      • 原理解析
      • 解决办法1
      • 解决办法2
    • 3.结语

1.介绍

在vue2里 v-forv-if一起用会出现一些不可预料的问题,因为v-for的优先级会比v-if要高,所以v-if会在每个for循环里面都会执行,当你需要根据条件渲染文本的时候,文本可能会渲染多次.

在vue2官方文档里面是这样描述这个问题的:

在这里插入图片描述

2.案例

这是我同学在学习vue2过程中遇到的该问题.

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>#app {width: 600px;margin: auto;}.tb {border-collapse: collapse;}.tb tr th {color: white;}.tb tr th,.tb tr td {padding: 5px 40px;border: 1px solid #5e5e5e;text-align: center;}.tb tr:nth-child(1) {background-color: rgb(94, 188, 255);}</style></head><body><div id="app"><table><table class="tb"><tr><th>编号</th><th>品牌名称</th><th>创立时间</th><th>操作</th></tr><!-- 循环渲染的元素tr --><tr v-if="list.length > 2" v-for="(item,index) in list" :key="item.id"><td>{{index+1}}</td><td>{{item.name}}</td><td>{{item.time}}</td><td><button @click="del(item.id)">删除</button></td></tr><tr v-else><td colspan="4">没有数据咯~</td></tr></table></table></div><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.13/vue.js"></script><script>const app = new Vue({el: "#app",data: {list: [{ id: +new Date(), name: "奔驰", time: "2020 - 05 - 01" },{ id: +new Date() + 1, name: "宝马", time: "2024 - 02 - 09" },{ id: +new Date() + 2, name: "奥迪", time: "2021 - 08 - 03" },],},methods: {del(id) {this.list = this.list.filter(item => item.id != id);},},});</script></body>
</html>

可以看到模板里面很明显的同时使用了v-for和v-if,但看表面逻辑是没有什么问题的,接下来我们看一下渲染结果和逻辑是否正确.
在这里插入图片描述

逻辑看起来是对的 当list.length > 2时正常显示 当 list.length<=2时显示没有数据咯

但是为什么没有数据咯渲染了两次呢?

要知道这个问题是怎么造成的我们首先要知道vue的渲染逻辑

原理解析

vue的渲染逻辑无非就是 解析#app里面的html模板将它转换为ast语法树 再通过将语法树转换为render函数

render函数里面包含 _v _s _ c _l _m这几个方法

上面的案例编译出来的render函数如下

(function anonymous() {with (this) {return _c('div', {attrs: {"id": "app"}}, [_c('table'), _c('table', {staticClass: "tb"}, [_c('tbody', [_m(0), _v(" "), _l((list), function(item, index) {return (list.length > 2) ? _c('tr', {key: item.id}, [_c('td', [_v(_s(index + 1))]), _v(" "), _c('td', [_v(_s(item.name))]), _v(" "), _c('td', [_v(_s(item.time))]), _v(" "), _c('td', [_c('button', {on: {"click": function($event) {return del(item.id)}}}, [_v("删除")])])]) : _c('tr', [_c('td', {attrs: {"colspan": "4"}}, [_v("没有数据咯~")])])})], 2)])])}
}
)
  • _v:创建文本节点
  • _s:替换变量为一个文本,变量的值从Vue里面的data对象拿
  • _c:创建一个dom节点
  • _l:v-for的实现
  • _m:标识静态render函数,静态render就是渲染时没用到动态数据的 所以渲染结果永远不会变

可以看到,因为v-for的优先级比v-if高 所以就算list.length <= 2 了 v-for还是会循环两次 而不是直接进入v-for在这里插入图片描述

所以v-else里面的内容会渲染两次

这样上面的渲染结果就说的通了,那该怎么解决这种问题呢?

解决办法1

上面的逻辑无非就是在list.length小于等于2的时候显示没有数据咯 那我们就不要在模板里面编写逻辑 在del方法里面编写逻辑 当list.length小于等于2的时候直接把list清空 然后没有数据咯的显示条件就是list.length === 0.

代码实现:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>#app {width: 600px;margin: auto;}.tb {border-collapse: collapse;}.tb tr th {color: white;}.tb tr th,.tb tr td {padding: 5px 40px;border: 1px solid #5e5e5e;text-align: center;}.tb tr:nth-child(1) {background-color: rgb(94, 188, 255);}</style></head><body><div id="app"><table><table class="tb"><tr><th>编号</th><th>品牌名称</th><th>创立时间</th><th>操作</th></tr><!-- 循环渲染的元素tr --><tr v-for="(item,index) in list" :key="item.id"><td>{{index+1}}</td><td>{{item.name}}</td><td>{{item.time}}</td><td><button @click="del(item.id)">删除</button></td></tr><tr v-if="list.length === 0"><td colspan="4">没有数据咯~</td></tr></table></table></div><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.13/vue.js"></script><script>const app = new Vue({el: "#app",data: {list: [{ id: +new Date(), name: "奔驰", time: "2020 - 05 - 01" },{ id: +new Date() + 1, name: "宝马", time: "2024 - 02 - 09" },{ id: +new Date() + 2, name: "奥迪", time: "2021 - 08 - 03" },],},methods: {del(id) {this.list = this.list.filter(item => item.id != id);if (this.list.length <= 2) this.list = [];},},});</script></body>
</html>

页面逻辑如下

在这里插入图片描述

可以看到逻辑已经正常了.

解决办法2

仔细看看上面的渲染逻辑 因为v-else只要上面的v-if没成立 就会进入v-else 所以才会渲染两次v-else

所以我们只要把v-else改成v-if=“list.length === 2” 就可以了, 相当于两个if分开了 这样v-for循环就只会执行一个if而不是第一个if没成立就直接用v-else 这样render函数就会变成:

(function anonymous() {with (this) {return _c('div', {attrs: {"id": "app"}}, [_c('table'), _c('table', {staticClass: "tb"}, [_c('tbody', [_m(0), _v(" "), _l((list), function(item, index) {return (list.length > 2) ? _c('tr', {key: item.id}, [_c('td', [_v(_s(index + 1))]), _v(" "), _c('td', [_v(_s(item.name))]), _v(" "), _c('td', [_v(_s(item.time))]), _v(" "), _c('td', [_c('button', {on: {"click": function($event) {return del(item.id)}}}, [_v("删除")])])]) : _e()}), _v(" "), (list.length === 2) ? _c('tr', [_c('td', {attrs: {"colspan": "4"}}, [_v("没有数据咯~")])]) : _e()], 2)])])}
}
)

其中_e()是创建一个空文本节点也就是条件不满足的时候渲染一个空节点并把他标识为注释 到时候渲染的时候该节点就会被渲染成一个html注释

3.结语

vue2里面的渲染逻辑还是有些小问题 不过在Vue3里面已经全面修复了并且大幅提升了渲染性能,所以在2024年的今天还是推荐大家使用Vue3

Hi👋,这里是瑞雨溪->一个喜欢JavaScript和Vue的大学生,如果我的文章给你带来的帮助,欢迎您关注我我会持续不断的更新更多优质文章.你的关注就是我的动力!!!🎉🎉🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/53129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg源码:skip_bits、skip_bits1、show_bits函数分析

GetBitContext结构体和其相关的函数分析&#xff1a; FFmpeg中位操作相关的源码&#xff1a;GetBitContext结构体&#xff0c;init_get_bits函数、get_bits1函数和get_bits函数分析 FFmpeg源码&#xff1a;skip_bits、skip_bits1、show_bits函数分析 一、skip_bits函数 skip…

使用Java实现高效用户行为监控系统

引言 背景介绍:随着Web应用的日益复杂和用户体验成为产品成功的关键因素,用户行为监控(User Behavior Monitoring, UBM)变得越来越重要。UBM不仅帮助开发者理解用户如何与应用程序交互,还能用于性能优化、错误追踪、用户体验改进等方面。目标读者:本文面向Java开发者、系…

使用cmd命令窗口操作mongodb

一、效果显示 二、下载MongoDB 1. 在官网下载安装MongoDB 官网网址&#xff1a;Download MongoDB Community Server | MongoDB 我安装的版本是7.0.14(注意安装到空闲磁盘) 三、启动MongoDB服务 1. 配置环境变量 注意替换为你的路径。 2. 在MongoDB的data下创建db文件夹 在…

51单片机应用开发---二进制、十六进制与单片机寄存器之间的关系(跑马灯、流水灯实例)

实现目标 1、掌握二进制与十六进制之间的转换 2、掌握单片机寄存器与二进制、十六进制之间的转换 3、掌握单片机驱动跑马灯、流水灯的原理 一、二进制与十六进制之间的转换 1、二进制 二进制&#xff08;binary&#xff09;&#xff0c; 是在数学和数字电路中以2为基数的…

计算机毕业设计 乡村生活垃圾管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Java接口与继承:构建灵活系统的基石

在Java编程语言中&#xff0c;接口&#xff08;Interface&#xff09;是一种定义方法规范的类型&#xff0c;它是一种特殊的抽象类&#xff0c;可以被类实现&#xff08;Implement&#xff09;或被其他接口继承&#xff08;Extend&#xff09;。接口是Java实现多态和模块化设计…

无人机之控制距离篇

无人机的控制距离是一个复杂且多变的概念&#xff0c;它受到多种因素的共同影响。以下是对无人机控制距离及其影响因素的详细分析&#xff1a; 一、无人机控制距离的定义 无人机控制距离指的是遥控器和接收机之间的最远传输距离。这个距离决定了无人机在操作者控制下能够飞行的…

前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)

图形验证码是网站安全防护的重要组成部分&#xff0c;能有效防止自动化脚本进行恶意操作&#xff0c;如何实现一个简单的运算图形验证码&#xff1f;本文封装了一个简单的js类&#xff0c;可以用于生成简单但安全的图形验证码。它支持自定义验证码样式&#xff0c;包括字体大小…

HarmonyOS使用LocationButton获取地理位置

LocationButton LocationKit getAddressesFromLocation方法 步骤&#xff1a; 整合 LocationButton并获取经纬度通过 LocationKit 将经纬度转为地址信息将地址信息渲染到页面上处理异常情况&#xff08;闪退&#xff09; LocationButton({ icon: LocationIconStyle.LINE…

828华为云征文|Flexus云服务器X实例部署宝塔运维面板

本次华为云Flexus云服务器X实例部署宝塔运维面板教学&#xff0c;这次是推陈出新啊 之前的云耀云服务器L实例已经很不错了&#xff0c;大力赞叹华为云的 同时感谢华为云提供优惠卷&#xff0c;只能说白嫖真是太棒了 华为云近期正在筹办华为云828企业节活动&#xff0c;90款免…

JAVA与Python谁更适合后端?

Java和Python各有优势&#xff0c;选择哪种语言应根据项目的具体需求和团队的实际情况来决定。 小型团队或原型开发&#xff1a;如果项目规模小、需求变动频繁&#xff0c;或者需要快速开发产品原型&#xff0c;建议使用Python。大型项目或企业级应用&#xff1a;如果项目规模…

java 集合详解

简介要介绍 Java 集合&#xff0c;也叫作容器&#xff0c;主要是由两大接口派生而来&#xff1a;一个是 Collection接口&#xff0c;主要用于存放单一元素&#xff1b;另一个是 Map 接口&#xff0c;主要用于存放键值对。 Collection接口有三个子主要的子接口&#xff1a;Lis…

设计模式-依赖注入

在软件开发中&#xff0c;我们经常遇到这样的情况&#xff1a; 一个类依赖于另一个类或者服务来完成某些功能。然而&#xff0c;硬编码的依赖关系会导致代码耦合度过高&#xff0c;难以测试和维护。为了解决这个问题&#xff0c;我们引入了一种设计模式——依赖注入&#xff0…

探索学习Python的最佳开发环境和编辑器

Python&#xff0c;作为目前最受欢迎的编程语言之一&#xff0c;因其简洁明了的语法和强大的功能性而备受开发者喜爱。无论是数据科学、机器学习、Web开发还是自动化脚本&#xff0c;Python都有着广泛的应用。选择合适的开发环境和编辑器对于提高编程效率和学习体验至关重要。 …

ArcGIS Pro SDK (十六)公共设施网络 1 网络管理

ArcGIS Pro SDK (十六)公共设施网络 1 网络管理 文章目录 ArcGIS Pro SDK (十六)公共设施网络 1 网络管理1 获取公共设施网络1.1 从表中获取公共设施网络1.2 从图层获取公共设施网络2 元素2.1 从元素中获取行3 编辑关联3.1 创建公共设施网络关联3.2 在单个编辑操作中创建公…

Parallels Desktop 20破解版(Mac虚拟机) v20.0.0 for Mac 最新商业版(支持M系列)

Parallels Desktop 20是一款目前功能最强大灵活度最高的虚拟机软件&#xff0c;可运行数千种 Windows 应用程序&#xff0c;如 Microsoft Office、Internet Explorer、Access、Quicken、QuickBooks、Visual Studio&#xff0c;甚至支持对图像要求较高的游戏和 CAD 项目&#xf…

渗透测试综合靶场 DC-2 通关详解

一、准备阶段 准备工具如Kali Linux&#xff0c;下载并设置DC-2靶场机。确保攻击机和靶机在同一网络段&#xff0c;通常设置为桥接模式或NAT模式。 1.1 靶机描述 Much like DC-1, DC-2 is another purposely built vulnerable lab for the purpose of gaining experience in …

python毕业设计作品:python手机数码商城系统毕业设计源代码作品和开题报告(Django框架)

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

Web 创建设计

Web 创建设计 Web 创建设计是一个涉及多个方面的过程,它包括网站的视觉设计、用户界面设计、用户体验设计、前端开发以及后端开发等。本文将详细介绍这些方面,并探讨如何创建一个既美观又实用的网站。 1. 视觉设计 视觉设计是网站创建设计的第一步,它决定了网站的外观和感…

Explain执行计划

Explain执行计划 explain可以帮助开发人员分析SQL问题&#xff0c;explain用于显示MySQL如何使用SQL执行计划&#xff0c;可以帮助开发人员写出更优化的查询语句。使用方法就是在查询语句前加上explain关键字。 执行添加上explain关键字的语句可以看到一个列表&#xff1a; 其…