vue源码解析——v-if和v-for哪个优先级高,如何避免两者同时使用

首先,官方不推荐v-if和v-for在同一个元素上使用。其次,如果两者同时使用,v-if和v-for的优先级怎么确定?在vue2和vue3中这两者的优先级顺序不一样。vue2是v-for优先,条件不存在时也会渲染多个注释节点。在vue3中进行了改进,v-if优先级高。在vue3中,v-if在编译阶段进行了静态节点提升,所以在v-for遍历每个节点,v-if对单个节点判断,这种情况会报错。不管是vue2还是vue3,都推荐,将v-for遍历的数组用计算属性改写,根据v-if依赖的条件返回过滤后的数组。

在介绍v-if和v-for的时候,最直观的方式就是去官方提供的模板编译网站,看v-if和v-for同时使用后编译成的结果。

vue2的模板地址:Vue Template Explorer

vue3的模板编译地址:Vue Template Explorer

 vue2测试

在li标签上同时使用v-for和v-if

<template><div><li v-for="item in arr" :key="item" v-if="exists"></li></div>
</template><script>
export default {data() {return {arr: [1, 2, 3, 4],exists: false,};},
};
</script><style></style>

 编译就会报错,让你把v-if移到上面标签

如果v-if使用了v-for遍历的item。编译器会提示你使用计算属性过滤满足条件的数组

vue2模板编译

v-if和v-for同时存在

OK,借用vue2的模板编译,看下代码编译后的结果。

function render() {with(this) {return _c('div', _l((arr), function (item) {return (exists) ? _c('li', {key: item}) : _e()}), 0)}
}

根据 arr 数组的长度和 exists 的值,渲染一个由 <li> 元素组成的列表。如果 exists 的值为假,则不渲染任何列表元素。因此是先遍历数组,在判断每项。即使不存在,也会创建一个空的注释节点。注释没有内容。

v-if引用了v-for遍历的item内容

<div><li v-for="item in arr" :key="item" v-if="item % 2">item</li></div>

 得到如下结果。可以看到,在vue2中是支持v-if和v-for的同时存在。先循环,在对item%2进行逻辑判断。

function render() {with(this) {return _c('div', _l((arr), function (item) {return (item % 2) ? _c('li', {key: item}, [_v("item")]) : _e()}), 0)}
}

  • with(this) { ... }:这段代码用于在渲染函数中使用 this 关键字,可以简化对组件实例属性的访问。
  • _c('div'):这段代码用于创建一个 div 元素,返回一个虚拟 DOM 节点。
  • _l((arr), function (item) { ... }):这段代码用于创建一个包含多个 li 元素的数组,每个 li 元素对应 arr 数组的一个元素。其中 arr 是一个组件实例的属性,表示要渲染的数组。
  • (item % 2):这段代码用于判断当前 item 的值是否能被 2 整除,返回一个布尔值。
  • _c('li', { key: item }):这段代码用于创建一个 li 元素,并设置 key 属性为当前 item 的值。
  • _v("item"):这段代码用于创建一个文本节点,其值为字符串 "item"。
  • _e():这段代码用于创建一个空的虚拟 DOM 节点,表示当前 item 不需要渲染为 li 元素。
  • 0:这个数字表示在 div 元素中渲染 li 元素的位置,这里表示在第一个位置。

vue3测试

v-if引用了v-for遍历的item内容

直接举例v-if和v-for同时存在,并且v-if引用了v-for的遍历结果。可以看到控制台报错,item未定义。这是因为item在编译为渲染函数的时候提到v-for的上面一层了。使用的时候还没在定义。

<template><div><li v-for="item in arr" :key="item" v-if="item % 2">item</li></div>
</template><script lang="ts" setup>
import { ref } from "vue";
const exists = ref(false);
let arr = ref([1, 2, 3, 4]);
</script>

vue3模板编译

可以看到vue3编译后v-if被提到外面。首先会判断 (_ctx.item % 2),这里item未定义,因为item是在v-for定义的,所以会报错。判断完v-if的条件,假设条件是对的,会执行第一个渲染列表每项。如果条件不满足,创建一个注释节点,与vue2不同,这里注释的内容有一个v-if标识。

在 Vue 中很多地方都运用了注释节点来作为占位节点,其目的是在不展示该元素的时候,标识其在页面中的位置,以便在 patch 的时候将该元素放回该位置。

import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode } from "vue"export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createElementBlock("div", null, [(_ctx.item % 2)? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.arr, (item) => {return (_openBlock(), _createElementBlock("li", { key: item }, "item"))}), 128 /* KEYED_FRAGMENT */)): _createCommentVNode("v-if", true)]))
}
  • (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.arr, (item) => { ... })这一行的作用是渲染一个列表,它使用 _renderList 函数来渲染 _ctx.arr 数组中的每个元素。如果当前 item 是偶数,则渲染一个 li 元素,并将其作为子节点插入到列表中。这里使用了 _Fragment 函数,用于将多个子节点合并为一个单一的虚拟节点。
  • _createCommentVNode("v-if", true) 这一行创建一个注释节点,表示在条件不满足的情况下不渲染任何内容。

vue2源码分析

v-if和v-for是不是写在模板template里,那么它们的源码就去模板编译过程去找。编译有三个过程,parse将模板解析为AST语法树->optimize优化AST语法树->codegen生成编译后的code。在最后codegen过程中,会先解析AST树中的与v-for相关的属性,再解析与v-if相关的属性。

genElement函数

在源码 vue-main\src\compiler\codegen\index.ts文件中

其实从此处可以初步知道为什么v-for优先级比v-if高,因为解析ast树生成渲染函数代码时,会先解析ast树中涉及到v-for的属性。然后再解析ast树中涉及到v-if的属性。而且genFor在会把el.forProcessed置为true,防止重复解析v-for相关属性。

genFor\genIf函数

vue-main\src\compiler\codegen\index.ts

 

以之前例子为例,处理liast树时,会先调用genElement,处理到for属性时,此时forProcessed为虚值,此时调用genFor处理li树中的v-for相关的属性。然后再调用genElement处理li树,此时因为forProcessedgenFor中已被标记为true。因此genFor不会被执行,继而执行genIf处理与v-if相关的属性。

vue3

在vue3中没有那个代码能够明显看出v-if和v-for的优先级

只有这个文件稍微体现了某个处理过程中对v-if和v-for同时存在的处理

在core-main\packages\compiler-core\src\transforms\vIf.ts文件中

 createIfBranch函数

在这个函数中,可以看出当v-ifv-for同时使用时,Vue 3会根据条件判断是否为<template>元素以及是否存在v-for指令来决定v-if的条件判断应用在哪个节点上。具体来说,如果节点是<template>元素且没有v-for指令,那么v-if的条件判断会被应用在<template>元素的子节点上;否则,v-if的条件判断会被应用在当前节点上。

 虽然这段代码没有直接提到“静态提升”,但根据Vue 3的设计,Vue 3会在编译阶段对模板进行静态分析,并对v-if进行静态提升,以提高性能。因此,可以理解为在这个函数中,Vue 3会对v-if进行静态提升,以确保条件判断的准确性和性能优化。

vue2 VS vue3

  • 在Vue 2中,由于v-for的优先级高于v-if,当v-if使用了v-for的遍历结果时,Vue 2会对每个元素都执行v-if条件判断。这可能导致性能问题,特别是在数据量较大时。
  • 而在Vue 3中,由于v-if的优先级高于v-for,Vue 3会在编译阶段对v-if进行静态提升(static hoisting),只对整个元素进行一次条件判断,而不会对每个元素都执行条件判断。这样可以提高性能,特别是在大型列表渲染时

v-ifv-for同时作用在同一个元素上,并且v-if使用了v-for的遍历结果时,两个版本的处理方式有所不同:

vue2会正常渲染。因为vue2先对for展开,再对v-if使用的item进行判断。

而vue3会发出警告。控制台会警告,item未定义。因为vue3先使用了v-if,在使用v-if的时候找不到item。所以尽量不要用v-if分析v-for里的内容。

 如何避免同时使用v-if和v-for

为了避免同时使用v-ifv-for,可以考虑以下几种方法:

  1. 使用计算属性或方法:将需要根据条件筛选的数据在组件中提前处理好,然后在模板中只使用v-for进行循环展示。
  2. 使用过滤器:通过过滤器对数据进行筛选,然后在模板中只使用v-for进行循环展示。
  3. 使用嵌套元素:将需要条件判断的元素放置在另一个包裹元素内,然后在外层元素上使用v-for,在内层元素上使用v-if。目的就是让v-if和v-for分开

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

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

相关文章

互联网大厂ssp面经(操作系统:part1)

1. 什么是进程和线程&#xff1f;它们之间有什么区别&#xff1f; a. 进程是操作系统中运行的一个程序实例。它拥有独立的地址空间和资源&#xff0c;可以独立执行。 b. 线程是进程内的一个执行单元&#xff0c;一个进程可以包含多个线程。 c. 线程共享进程的资源&#xff0c;…

HarmonyOS开发实例:【数字管家app】

一&#xff0e;概述 本应用是基于RK3399开发板&#xff0c;使用OpenHarmony3.1-Release开发的应用。通过OpenHarmony的分布式技术&#xff0c;使多人能够一起画画。 1.应用运行效果图&#xff1a; 2.分布式画板使用示意图 如上图所示&#xff0c;用户1、用户2在各自本地端进行…

【Entity Framework】如何使用EF中的生成值

【Entity Framework】如何使用EF中的生成值 文章目录 【Entity Framework】如何使用EF中的生成值一、概述二、默认值三、计算列四、设置主键五、显示配置值生成六、设置日期/时间值生成6.1 创建时间戳6.2 更新时间戳 七、替代值生成八、无值生成九、总结 一、概述 数据库列的值…

【网站项目】校园订餐小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

软考121-上午题-【软件工程】-敏捷方法

一、敏捷方法 敏捷开发的总体目标是通过“尽可能早地、持续地对有价值的软件的交付”使客户满意。通过在软件开发过程中加入灵活性&#xff0c;敏捷方法使用户能够在开发周期的后期增加或改变需求。 敏捷过程的典型方法有很多&#xff0c;每一种方法基于一套原则&#xff0c;这…

国家统计局行政区划获取及入库ES实践

我们先看下最终效果&#xff1a; 1. ES索引新建 PUT administrative_division {"mappings": {"properties": {"province": {"type": "keyword"},"province_code": {"type": "keyword"},&q…

【前端Vue】Vue3+Pinia小兔鲜电商项目第5篇:整体认识和路由配置,本资源由 收集整理【附代码文档】

Vue3ElementPlusPinia开发小兔鲜电商项目完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;认识Vue3&#xff0c;使用create-vue搭建Vue3项目1. Vue3组合式API体验,2. Vue3更多的优势,1. 认识create-vue,2. 使用create-vue创建项目,1. setup选项的写法和执行…

mobaXterm使用密钥免密登录服务器,并且在Vscode中使用ppk密钥进行远程连接

本文介绍在mobaXterm上免密登录的过程&#xff0c;并且在vscode中也免密登录服务器。 1. mobaXterm免密登录服务器 需要首先说明的是&#xff0c;mobaXterm里有一个记住密码的功能。如果你只是不想手动输入密码&#xff0c;大多数情况下使用这一功能即可。 这里介绍的情况是…

今天讲讲MYSQL数据库事务怎么实现的!

目录 什么是数据库事务 Mysql如何保证原子性 Mysql如何保证持久性 MySQL怎么保证隔离性 事务隔离级别 脏读的解决 不可重复读的解决 幻读的解决 MVCC实现 Read View 那么RC、RR级别下的InnoDB快照读有什么不同&#xff1f; 什么是数据库事务 数据库事务是指一组数据…

vs2017离线安装(配合QT5.9.2使用)

以vs2017_Professional版本为例&#xff1a; 一、下载安装包vs2017_Professional.exe&#xff08;在线安装包即可&#xff09; 二、创建在目录&#xff1a;C:\vs2017_Professional_Package&#xff0c;把vs2017_Professional.exe放在该目录下。 ID&#xff1a; Microsoft.Vis…

一文了解AI边缘计算盒子是什么产品设备

大家听说过AI边缘计算盒子吗&#xff1f;不知道你有没有注意到&#xff0c;最近这款产品设备在科技圈内可是火得不要不要的&#xff01;那么&#xff0c;它究竟是什么东西呢&#xff1f;别着急&#xff0c;小编我今天就来给大家揭晓。 边缘计算盒子是什么? 边缘计算盒子是一种…

算法与程序设计(实验2)----分治法求最近点对问题

一&#xff0e;实验目的 掌握分治法思想。学会最近点对问题求解方法。 二、实验内容 1. 对于平面上给定的N个点&#xff0c;给出具有最短距离的两点。 2. 要求随机生成N个点的平面坐标&#xff0c;应用蛮力法编程计算出所有点对的最短距离。 3. 要求随机生成N个点的平面坐…

Linux LVM磁盘扩容

1、查看磁盘情况 df -h df -h2、查看逻辑卷 lvdisplay lvdisplay3、查看逻辑组 vgdisplay vgdisplay4、查看物理卷 pvdisplay pvdisplay5、查看磁盘 fdisk -l fdisk -l6、磁盘分区fdisk /dev/磁盘名 # 上一步查看到的新硬盘路径 fdisk /dev/vdb7、格式化磁盘mkfs -t ext4…

KaiwuDB 数据库故障诊断工具详解

数字化时代&#xff0c;数据是企业最宝贵的资产之一。然而&#xff0c;随着数据量的增长&#xff0c;数据库管理的复杂性也在不断上升。数据库故障可能导致业务中断&#xff0c;给公司带来巨大的财务和声誉损失。在本篇博客中&#xff0c;我们将分享 KaiwuDB 是如何设计故障诊断…

ssm038汽车养护管理系统+jsp

汽车养护管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本汽车养护管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

MySQL——全文检索

不是所有的数据表都支持全文检索 MySQL支持多种底层数据库引擎&#xff0c;但是并非所有的引擎支持全文检索 &#xff0c;目前最常用引擎是是MyISAM和InnoDB&#xff1b;前者支持全文检索&#xff0c;后者不支持。 booolean模式操作符 实验&#xff1a; 表productnotes &…

SQL Server详细安装使用教程

1.安装环境 现阶段基本不用SQL Server数据库了&#xff0c;看到有这样的分析话题&#xff0c;就把多年前的存货发一下&#xff0c;大家也可以讨论看看&#xff0c;思路上希望还有价值。 SQL Server 2008 R2有32位版本和64位版本&#xff0c;32位版本可以安装在Windows XP及以上…

《QT实用小工具·二十》存款/贷款计算器

1、概述 源码放在文章末尾 该项目实现了用于存款和贷款的计算器的功能&#xff0c;如下图所示&#xff1a; 项目部分代码如下&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget>namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJ…

【13137】基于TQM的人力资源管理

目录 1.单选题 2.多选题 3.名词解释题 4.简答题 1.单选题

【智能算法应用】灰狼算法求解TSP问题

目录 1.算法原理2.TSP数学模型3.结果展示4.参考文献 1.算法原理 【智能算法】灰狼算法&#xff08;GWO&#xff09;原理及实现 2.TSP数学模型 旅行商问题&#xff08;TSP&#xff09;是一种著名的组合优化问题&#xff0c;它涉及寻找给定一组城市及其之间的距离或成本&#…