Vue指令:v-for列表循环
suiw9 2024-12-01 03:59 14 浏览 0 评论
1. 数组的循环
用 v-for 指令根据一组数组的选项列表进行渲染。
1.1 通过索引渲染数组内容
通过数组的索引获取数组的数据
<div id="app">
<ul>
<li>{{ fruites[0] }}</li>
<li>{{ fruites[1] }}</li>
<li>{{ fruites[2] }}</li>
<li>{{ fruites[3] }}</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:["苹果","梨子","西瓜","榴莲"]
},
})
</script>
这种写法在数据很多的时候或者数据发生更新的时候处理就会很繁琐,
因此我们可以使用v-for指令来循环数组
1.2 数组循环语法
1.2.1语法说明:
- v-for 指令需要使用 item in items 形式的特殊语法,
- item 是数组元素迭代的别名。
- items 是原数据数组
1.2.2v-for指令的语法使用示例:
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
1.2.3 数组循环示例
基本数组的循环
<div id="app">
<ul>
<li v-for="fruite in fruites">
{{fruite}}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:["苹果","梨子","西瓜","榴莲"]
},
})
</script>
1.2.4 获取数组索引
v-for 还支持一个可选的第二个参数为当前项的索引。
<div id="app">
<ul>
<li v-for="(fruite,index) in fruites">
{{fruite}}--{{index}}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:["苹果","梨子","西瓜","榴莲"]
},
})
</script>
1.2.5 数组项为对象
数组项为对象的循环
<div id="app">
<ul>
<li v-for="fruite in fruites">
<span>{{fruite.name}}:</span>
<span>{{fruite.price}}</span>
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:[
{
name:"苹果",
price: "5元/斤"
},
{
name:"梨子",
price: "6元/斤"
},
{
name:"西瓜",
price: "8元/斤"
},
{
name:"榴莲",
price: "12元/斤"
}
]
}
})
</script>
使用索引
<div id="app">
<ul>
<li v-for="(fruite,index) in fruites">
<span>{{index+1}}</span>
<span>{{fruite.name}}:</span>
<span>{{fruite.price}}</span>
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:[
{
name:"苹果",
price: "5元/斤"
},
{
name:"梨子",
price: "6元/斤"
},
{
name:"西瓜",
price: "8元/斤"
},
{
name:"榴莲",
price: "12元/斤"
}
]
}
})
</script>
1.2.6 使用of循环
同时我们也可以用of替代in作为分割符
语法
<div v-for="item of items"></div>
示例:
<div id="app">
<ul>
<li v-for="(fruite,index) of fruites">
{{fruite}}--{{index}}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:["苹果","梨子","西瓜","榴莲"]
},
})
</script>
2. 对象的循环
也可以用 v-for 指令来循环对象。
第一个参数是训练遍历对象的属性值:
<div id="app">
<ul>
<li v-for="value in users">
{{ value }}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
users:{
name:'Henry',
age: 22,
work: "前端工程师",
like: "看书"
}
}
})
</script>
第二个的参数为对象的属性(键名):
<div id="app">
<ul>
<li v-for="(value,key) in users">
{{key}} : {{ value }}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
users:{
name:'Henry',
age: 22,
work: "前端工程师",
like: "看书"
}
}
})
</script>
还可以通过第三个参数来获取索引值:
<div id="app">
<ul>
<li v-for="(value,key,index) in users">
{{index}}. {{key}} : {{ value }}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
users:{
name:'Henry',
age: 22,
work: "前端工程师",
like: "看书"
}
}
})
</script>
3. v-for循环中的 key属性
使用v-for更新已渲染的元素列表时,默认用就地复用策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素; 我们在使用的使用经常会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法;
key值的使用其实是和vue响应式已经虚拟DOM有关, 那么我们通过下面的例子来了解一下
例子:
数据
new Vue({
el: "#app",
data: {
fruites:[
{
id: 1,
name: '苹果',
},
{
id: 2,
name: '梨子',
},
{
id: 3,
name: '西瓜',
},
]
}
})
页面渲染
<div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
但是数据发生了变化,
new Vue({
el: "#app",
data: {
fruites:[
{
id: 1,
name: '苹果',
},
{
id: 2,
name: '梨子',
},
{
id: 3,
name: '西瓜',
},
{
id: 4,
name: '这是新增的水果',
},
]
}
})
如果数据是这一种变化的话, 那么index没什么问题
数据前后变化的结果
之前的数据 之后的数据
key:0 index: 0 name: "苹果" key:0 index: 0 name: "苹果"
key:1 index: 1 name: "梨子" key:1 index: 1 name: "梨子"
key:2 index: 3 name: "西瓜" key:2 index: 2 name: "西瓜"
key:3 index: 4 name: "这是新增的水果"
这样vue就会分析到 其他的数据 都不需要改变,只需要在新增一个DOM节点,然后添加新增的数据就可以了
可以输入我们是在数组中间插入的数据就会不一样为了
new Vue({
el: "#app",
data: {
fruites:[
{
id: 1,
name: '苹果',
},
{
id: 4,
name: '这是新增的水果',
},
{
id: 2,
name: '梨子',
},
{
id: 3,
name: '西瓜',
},
]
}
})
这时数据的对比
之前的数据 之后的数据
key:0 index: 0 name: "苹果" key:0 index: 0 name: "苹果"
key:1 index: 1 name: "梨子" key:1 index: 1 name: "这是新增的水果"
key:2 index: 3 name: "西瓜" key:2 index: 2 name: "梨子"
? key:3 index: 3 name: "西瓜"
通过上面清晰的对比,发现除了第一个数据可以复用之前的之外,另外三条数据都需要重新渲染;
是不是很惊奇,我明明只是插入了一条数据,怎么三条数据都要重新渲染?而我想要的只是新增的那一条数据新渲染出来就行了
最好的办法是使用数组中不会变化的那一项作为key值,对应到项目中,即每条数据都有一个唯一的id,来标识这条数据的唯一性;使用id作为key值,我们再来对比一下向中间插入一条数据,此时会怎么去渲染
<div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
此时数据的变化
之前的数据 之后的数据
key:0 id: 0 index: 0 name: "苹果" key:0 id: 0 index: 0 name: "苹果"
key:1 id: 1 index: 1 name: "梨子" key:4 id: 4 index: 1 name: "这是新增的水果"
key:2 id: 2 index: 3 name: "西瓜" key:1 id: 1 index: 2 name: "梨子"
? key:2 id: 2 index: 3 name: "西瓜"
现在对比发现只有一条数据变化了,就是id为4的那条数据,因此只要新渲染这一条数据就可以了,其他都是就复用之前的;
为什么需要key属性: 虚拟DOM的diff算法,
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:
即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
所以一句话,key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
4 不推荐**同时使用 v-if 和 v-for。
v-if和v-for一起使用,v-for的优先级要高于v-if
可能会想到v-if和v-for是用的两种情况
- 为了过滤一个列表中的项目
- 为了避免渲染本应该被隐藏的列表
那么接下来好好看看这两种情况
第一种情况: 为了过滤一个列表中的项目
为了过滤项目内容,我们可能会如下调用:
<li v-for = "fruite of fruites" v-if = "fruite.price > 22"></li>
在这种情况下,请将users替换为一个计算属性(比如activeUsers),让其返回过滤后的列表。
示例详解:
<div id="app">
<ul>
<li
v-for="fruite of fruites"
:key="fruite.id"
>
名称: {{ fruite.name}} -- 价格: {{ fruite.price}}元/斤
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:[
{
id: 1,
name: '苹果',
price: 20,
},
{
id: 4,
name: '桃子',
price: 30,
},
{
id: 2,
name: '梨子',
price: 10,
},
{
id: 3,
name: '西瓜',
price: 50,
},
]
}
})
</script>
如果现在只想显示价格在22元以上的水果,我们可能会这么写
<ul>
<li
v-for="fruite of fruites"
v-if="fruite.price > 22"
:key="fruite.id"
>
名称: {{ fruite.name}} -- 价格: {{ fruite.price}}元/斤
</li>
</ul>
这么写固然会得到你想要的效果, 但是因为v-for和v-if优先级的关系, 所以将会经过如下的运算
this.fruites.map(function (fruite) {
if (fruite.price > 22) {
return user.name
}
})
因此,哪怕我们只渲染出一小部分内容,也得在每次重新渲染的时候遍历整个列表,无论价格是否满足我们的条件
随意我们推荐使用计算属性, 在计算属性中处理过滤事宜, 计算属性会在计算完毕后缓存内容,提高遍历的效率
<div id="app">
<ul>
<li
v-for="fruite of filterFruites"
:key="fruite.id"
>
名称: {{ fruite.name}} -- 价格: {{ fruite.price}}元/斤
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
fruites:[
{
id: 1,
name: '苹果',
price: 20,
},
{
id: 4,
name: '桃子',
price: 30,
},
{
id: 2,
name: '梨子',
price: 10,
},
{
id: 3,
name: '西瓜',
price: 50,
},
]
},
computed: {
filterFruites(){
return this.fruites.filter(fruite => fruite.price > 22)
}
}
})
</script>
这样我们得到的结果是一样的,但是我们获得了如下的好处
- 过滤后的列表只会在 fruites 数组发生相关变化时才被重新运算,过滤更高效。
- 使用 v-for = "fruite of filterFruites"之后,我们在渲染过滤后的数据,渲染更高效。
- 解藕渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。
第二种情况: 为了避免渲染本应该被隐藏的列表
也就是根据条件类判断列表的显示我们也后可能会使用下面的方法调用
<li v-for = "fruite of fruites" v-if = "isShow"></li>
实例详解:
<div id="app">
<ul>
<li
v-for="fruite of fruites"
v-if="isShow"
:key="fruite.id"
>
名称: {{ fruite.name}} -- 价格: {{ fruite.price}}元/斤
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
isShow: true,
fruites:[
{
id: 1,
name: '苹果',
price: 20,
},
{
id: 4,
name: '桃子',
price: 30,
},
{
id: 2,
name: '梨子',
price: 10,
},
{
id: 3,
name: '西瓜',
price: 50,
},
]
}
})
</script>
原理是一样的, 就是如果这么写, 还是会循环遍历每一个数据,然后判断是不是显示. 一样浪费
所以我们将 v-if 移动到容器元素,这样我们就不用对每一个元素都进行判断是否显示, 取而代之的是,我们只检查判断一次,且不会在 isShow 为假的时候还循环运算 v-for。
<div id="app">
<ul v-if="isShow">
<li
v-for="fruite of fruites"
:key="fruite.id"
>
名称: {{ fruite.name}} -- 价格: {{ fruite.price}}元/斤
</li>
</ul>
</div>
5.显示(过滤/排序)结果
有时,我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。在这种情况下,可以使用计算属性和方法来过滤数据
我们上面讲过了计算属性,下面来看看方法的使用
<!-- HTML -->
<li v-for="n in even(numbers)">{{ n }}</li>
<!-- js -->
<script>
new Vue({
el: "#app",
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
})
</script>
6 二维数组循环
<div id="app">
<ul>
<li v-for='(fruit,index) in fruites'>
{{index+1}}. {{fruit.name}}
<ul>
<li v-for="(c,childrenIndex) in fruit.color">
{{index+1}}.{{childrenIndex+1}} {{c}}
</li>
</ul>
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
fruites: [
{ name: '香蕉', color: ['green', 'yellow'] },
{ name: '苹果', color: ['red', 'yellow', 'green'] },
{ name: '西瓜', color: ['pink'] },
]
}
})
</script>
7 其他不常用的循环
<!-- 循环字符串 -->
<div id="app">
<div v-for="c in 'abcd'">{{c}}</div>
</div>
<!-- 循环数字 -->
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
<!-- 借用template来循环嵌套多个元素 -->
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
总结示例:
<!-- vue-app 是根容器 -->
<div id='vue-app'>
<h1> v-for 循环</h1>
<!-- 数组下标获取 -->
{{ characters[0] }}
{{ characters[1] }}
{{ characters[2] }}
<!-- 遍历数组 -->
<ul>
<li v-for="character in characters"> {{ character }}</li>
</ul>
<ul>
<li v-for = "user in users">
{{ user.name }} - {{ user.age }}
</li>
</ul>
<!-- 获取数组的下标(数组的每一项,数组的下标) -->
<ul>
<li v-for = "(user,index) in users">
{{ index }}. {{ user.name }} - {{ user.age }}
</li>
</ul>
<!-- 不适用列表标签的循环 -->
<div v-for = "(user,index) in users">
<h2>{{ index }}. {{ user.name }}</h2>
<p>{{ user.age }}</p>
</div>
<!-- 上边的div渲染处理后时空标签,<template>去除空标签 -->
<template v-for = "(user,index) in users">
<h2>{{ index }}. {{ user.name }}</h2>
<p>{{ user.age }}</p>
</template>
<!-- <template>标签是不会进行渲染的 -->
<!-- 循环json数据的key值和val值 -->
<template v-for = "(user,index) in users">
<div v-for="(val,key) in user">
{{ index }}. {{key}}:{{val}}
</div>
</template>
</div>
<script>
//实例化Vue对象
new Vue({
el: "#vue-app",
data: {
characters:["苹果","梨子","西瓜"],
users:[
{name:"苹果",price: 30},
{name:"梨子",price: 25},
{name:"西瓜",price: 18}
]
}
})
</script>
相关推荐
- 10款超实用JavaScript音频库(js播放音频代码)
-
HTML5提供了一种新的音频标签实现和规范用一个简单的HTML对象而无需音频插件来控制音频。这只是一个简单的整合这些新的HTML5音频特征及使用JavaScript来创建各种播放控制。下面将介绍10款...
- PROFINET转Modbus网关——工业协议融合的智能枢纽
-
三格电子SG-PNh750-MOD-221,无缝连接Profinet与Modbus,赋能工业物联产品概述...
- 简单实用的Modbus类库,支持从站和DTU
-
一、简介...
- [西门子PLC] S7-200 SMART PROFINET :通过GSD组态PLC设备
-
从S7-200SMARTV2.5版本开始,S7-200SMART开始支持做PROFINETIO通信的智能设备。从而,两个S7-200SMART之间可以进行PROFINETI...
- Modbus(RTU / TCP)有什么异同(modbus tcp和tcp)
-
Modbus是一种广泛使用的工业自动化通信协议,它支持设备之间的数据交换。Modbus协议有两个主要的变体:ModbusRTU(二进制模式)和ModbusTCP(基于TCP/IP网络的模式)。尽管...
- Modbus通信调试步骤详解(modbus调试工具怎么用)
-
Modbus通信调试步骤详解 Modbus通信分为串口和以太网,无论是串口还是以太网,只要是标准Modbus,就可以用Modbus模拟器进行调试。按以下几步进行调试。...
- 理解Intel手册汇编指令(intel 汇编指令手册)
-
指令格式...
- 「西门子PLC」S7-200 SMART的Modbus RTU通讯
-
S7-200SMART集成的RS485端口(端口0)以及SBCM01RS485/232信号板(端口1)两个通信端口可以同时做MODBUSRTU主站,或者一个做MODBUSRTU主站一个做MO...
- InfiniBand网络运维全指南:从驱动安装到故障排查
-
一、InfiniBand网络概述InfiniBand(直译为“无限带宽”技术,缩写为IB)是一种用于高性能计算的计算机网络通信标准,具有极高的吞吐量和极低的延迟,用于计算机与计算机之间的数据互连。它...
- 一加回归 OPPO,背后的秘密不可告人
-
有这样一个手机品牌,它诞生于互联网品牌。在大众群体看来,它的身世似乎模糊不清,许多人以为它是国外品牌。它的产品定位是极客群体,深受国内发烧友,甚至国外极客玩家喜爱。...
- [西门子PLC] S7-200SMART快速高效的完成Modbus通信程序的设计
-
一、导读Modbus通信是一种被广泛应用的通信协议,在变频器、智能仪表还有其他一些智能设备上都能见到它的身影。本文呢,就把S7-200SMART系列PLC当作Modbus主站,把...
- 狂肝10个月手搓GPU,他们在我的世界中玩起我的世界,梦想成真
-
梦晨衡宇萧箫发自凹非寺量子位|公众号QbitAI自从有人在《我的世界》里用红石电路造出CPU,就流传着一个梗:...
- [西门子PLC] 博途TIA portal SCL编程基础入门:1-点动与自锁
-
一、S7-SCL编程语言简介...
- 工作原理系列之:Modbus(modbus工作过程)
-
MODBUS是一种在自动化工业中广泛应用的高速串行通信协议。该协议是由Modion公司(现在由施耐德电气公司获得)于1979年为自己的可编程逻辑控制器开发的。该协议充当了PLCS和智能自动化设备之间的...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
MacOS + AList + 访达,让各种云盘挂载到本地(建议收藏)
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
- 最近发表
-
- 10款超实用JavaScript音频库(js播放音频代码)
- Howler.js,一款神奇的 JavaScript 开源网络音频工具库
- PROFINET转Modbus网关——工业协议融合的智能枢纽
- 简单实用的Modbus类库,支持从站和DTU
- [西门子PLC] S7-200 SMART PROFINET :通过GSD组态PLC设备
- Modbus(RTU / TCP)有什么异同(modbus tcp和tcp)
- Modbus通信调试步骤详解(modbus调试工具怎么用)
- 理解Intel手册汇编指令(intel 汇编指令手册)
- 「西门子PLC」S7-200 SMART的Modbus RTU通讯
- InfiniBand网络运维全指南:从驱动安装到故障排查
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)