Vue指令:v-for列表循环
ztj100 2024-12-31 15:58 26 浏览 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>
相关推荐
- sharding-jdbc实现`分库分表`与`读写分离`
-
一、前言本文将基于以下环境整合...
- 三分钟了解mysql中主键、外键、非空、唯一、默认约束是什么
-
在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。...
- MySQL8行级锁_mysql如何加行级锁
-
MySQL8行级锁版本:8.0.34基本概念...
- mysql使用小技巧_mysql使用入门
-
1、MySQL中有许多很实用的函数,好好利用它们可以省去很多时间:group_concat()将取到的值用逗号连接,可以这么用:selectgroup_concat(distinctid)fr...
- MySQL/MariaDB中如何支持全部的Unicode?
-
永远不要在MySQL中使用utf8,并且始终使用utf8mb4。utf8mb4介绍MySQL/MariaDB中,utf8字符集并不是对Unicode的真正实现,即不是真正的UTF-8编码,因...
- 聊聊 MySQL Server 可执行注释,你懂了吗?
-
前言MySQLServer当前支持如下3种注释风格:...
- MySQL系列-源码编译安装(v5.7.34)
-
一、系统环境要求...
- MySQL的锁就锁住我啦!与腾讯大佬的技术交谈,是我小看它了
-
对酒当歌,人生几何!朝朝暮暮,唯有己脱。苦苦寻觅找工作之间,殊不知今日之事乃我心之痛,难道是我不配拥有工作嘛。自面试后他所谓的等待都过去一段时日,可惜在下京东上的小金库都要见低啦。每每想到不由心中一...
- MySQL字符问题_mysql中字符串的位置
-
中文写入乱码问题:我输入的中文编码是urf8的,建的库是urf8的,但是插入mysql总是乱码,一堆"???????????????????????"我用的是ibatis,终于找到原因了,我是这么解决...
- 深圳尚学堂:mysql基本sql语句大全(三)
-
数据开发-经典1.按姓氏笔画排序:Select*FromTableNameOrderByCustomerNameCollateChinese_PRC_Stroke_ci_as//从少...
- MySQL进行行级锁的?一会next-key锁,一会间隙锁,一会记录锁?
-
大家好,是不是很多人都对MySQL加行级锁的规则搞的迷迷糊糊,一会是next-key锁,一会是间隙锁,一会又是记录锁。坦白说,确实还挺复杂的,但是好在我找点了点规律,也知道如何如何用命令分析加...
- 一文讲清怎么利用Python Django实现Excel数据表的导入导出功能
-
摘要:Python作为一门简单易学且功能强大的编程语言,广受程序员、数据分析师和AI工程师的青睐。本文系统讲解了如何使用Python的Django框架结合openpyxl库实现Excel...
- 用DataX实现两个MySQL实例间的数据同步
-
DataXDataX使用Java实现。如果可以实现数据库实例之间准实时的...
- MySQL数据库知识_mysql数据库基础知识
-
MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...
- 如何为MySQL中的JSON字段设置索引
-
背景MySQL在2015年中发布的5.7.8版本中首次引入了JSON数据类型。自此,它成了一种逃离严格列定义的方式,可以存储各种形状和大小的JSON文档,例如审计日志、配置信息、第三方数据包、用户自定...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)