![Vue.js 3.0从入门到精通(视频教学版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/154/44510154/b_44510154.jpg)
5.1.3 v-for
使用v-for指令可以对数组、对象进行循环,来获取到其中的每一个值。
1.v-for指令遍历数组
使用v-for指令,必须使用特定语法alias in expression,其中items是源数据数组,而item则是被迭代的数组元素的别名,具体格式如下:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P73_164930.jpg?sign=1738983229-6Ym7QmCdLHcEhasV44wsRAkRLa679UOZ-0-09a9be650473deee3722a13645fef971)
下面看一个示例,使用v-for指令循环渲染一个数组。
【例5.4】v-for指令遍历数组(源代码\ch05\5.4.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P73_164931.jpg?sign=1738983229-SmsiHB2tI1dVDHVV3qJpoHU4uofkNy7e-0-d83bd5263b6ec0c8a8640d57e1aca7b1)
在浏览器中运行程序,按F12键打开控制台并切换到“Elements”选项,结果如图5-5所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P73_22306.jpg?sign=1738983229-ZfA9VIkGXwa3xvuKtxfWyxVnOZ4oZFzN-0-ea5e899a8d5d9ed59574022c73cbe544)
图5-5 v-for指令遍历数组
提示
v-for指令的语法结构也可以使用of替代in作为分隔符,例如:
<li v-for="item of nameList">
在v-for指令中,可以访问所有父作用域的属性。v-for还支持一个可选的第二个参数,即当前项的索引。例如,修改上面示例,添加index参数,代码如下:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_164932.jpg?sign=1738983229-iUkr9hQcqvLbApqaJSQ0em0MVskWwWS1-0-74eeed0db30bf91173874326808e6972)
在浏览器中运行程序,结果如图5-6所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_22434.jpg?sign=1738983229-xwAgoC3xKsLosaojToucJAhugDeKwMXJ-0-fa0849008a3f08b91797564f66b65fa2)
图5-6 v-for指令第二个参数
2.v-for指令遍历对象
遍历对象的语法和遍历数组的语法是一样的:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_165357.jpg?sign=1738983229-5SuAHbpmBU72jTti6rd3aAbQqVC8RyRn-0-c6f18affd30eda3ceffe089b3709efac)
其中object是被迭代的对象,value是被迭代的对象属性的别名。
【例5.5】v-for指令遍历对象(源代码\ch05\5.5.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_164933.jpg?sign=1738983229-rZ1PRM3cBsZKLTSJLrJOUy1zj30NiOuV-0-d12aa42d286c6e1c5fcf53675332e922)
在浏览器中运行程序,结果如图5-7所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P75_22948.jpg?sign=1738983229-JwwC0zxDPfNvHwgy7A0VCvUX2NjsAD74-0-9eb9ca860506cacdce1b76237c94567e)
图5-7 v-for指令遍历对象
还可以添加第二个参数,用来获取键值;获取选项的索引,可以添加第三个参数。
【例5.6】添加第二、三个参数(源代码\ch05\5.6.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P75_164935.jpg?sign=1738983229-hhgAaY2iXFu4kGboqVAL5cAcNN9I7jwy-0-3753a3e1ea7ef746e9f4f65240e8b954)
在浏览器中运行程序,结果如图5-8所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P76_23436.jpg?sign=1738983229-6ZAU4sjfYvqrngXsaYE2FtMQtX8I4KAa-0-f34c285f34d32698f211c3ace49b6cfe)
图5-8 添加第二、三个参数
3.v-for指令遍历整数
也可以使用v-for指令遍历整数。
【例5.7】v-for指令遍历整数(源代码\ch05\5.7.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P76_165358.jpg?sign=1738983229-XxkFayINVVtFsPiDOi8xSIYEg5HnxCt8-0-9bdf6b122b54501f406f88ef23a33f27)
在浏览器中运行程序,结果如图5-9所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P76_23701.jpg?sign=1738983229-evB2zTEcfJY2jMwB37bdpQepDRoWfurd-0-be5bf3a940b3dee7a2b08295144a12a1)
图5-9 v-for指令遍历整数
4.在<template>上使用v-for
类似于v-if,也可以利用带有v-for的<template>来循环渲染一段包含多个元素的内容。
【例5.8】在<template>上使用v-for(源代码\ch05\5.8.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P76_164937.jpg?sign=1738983229-1PAx8nZrLCR1zM8JG48gmFQprSWl8gV5-0-4cf80c5055ee5039e5033d479df034e0)
在浏览器中运行程序,按F12键打开控制台并切换到“Elements”选项,并没有看到<template>元素,结果如图5-10所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P77_24142.jpg?sign=1738983229-isyxrJJLZfPIp7EGA6dToKpdhM7znnbv-0-758ffc80d1940b65046294c0cdf730a7)
图5-10 在<template>上使用v-for
提示
template元素一般常和v-for和v-if一起结合使用,这样会使得整个HTML结构没有那么多多余的元素,整个结构会更加清晰。
5.数组更新检测
Vue将被监听的数组的变异方法进行了包裹,它们也会触发视图更新。被包裹过的方法包括push()、pop()、shift()、unshift()、splice()、sort()和reverse()。
【例5.9】数组更新检测(源代码\ch05\5.9.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P77_164939.jpg?sign=1738983229-jHDsfDib6U1B7czxMsaOhGJEbulydz5s-0-b99ce78a47e56c3d32645840b44ea5a8)
在浏览器中运行程序,结果如图5-11所示。按F12键打开控制台并切换到“Console”选项,在选项中输入“vm.nameList.push("1800台")”,按下Enter键,数据将添加到nameList数组中,在页面中也显示出添加的内容,如图5-12所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P78_24562.jpg?sign=1738983229-a9cCttnNTvC0rjRRr5t4nVRIWLYjgOtw-0-21eb5c4dc1460388eb19308d7b6f970b)
图5-11 初始化效果
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P78_24563.jpg?sign=1738983229-s9bCV6j18m6VLzwILOyRTgednX0W5oD3-0-0a151241c2dcf53a318a37a9210ee7df)
图5-12 修改数据对象中的数组属性
还有一些非变异方法,例如filter()、concat()和slice()。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组。
继续在浏览器控制台输入“vm.nameList=vm.nameList.concat(["2600台","畅销版"])”,把变更后的数组再赋值给Vue实例的nameList,按下Enter键,即可发现页面发生了变化,如图5-13所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P78_24567.jpg?sign=1738983229-FZVdFxitK0NTZh9EPgM5N0GHmxQXrg6N-0-81316d12b20820af22834698eb9e5313)
图5-13 使用新数组替换原始数组
可能会认为,这将导致Vue丢弃现有DOM并重新渲染整个列表,但事实并非如此。Vue为了使得DOM元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组,这是非常高效的操作。
在Vue 3.0版本中,可以利用索引直接设置一个数组项,例如修改上面示例:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_164941.jpg?sign=1738983229-NZm447PhPkfZIFRKy00htd5XHDNVBlyu-0-915cd01c47fdf38c4c59a33eba0b8bd0)
在浏览器中运行程序,结果如图5-14所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_24878.jpg?sign=1738983229-hf2yqKgYeDHIW1EWtp4fK1PQTFvM1EP2-0-f05940bfb6ba41d2ce4b97ceb2049c9e)
图5-14 通过索引向数组添加元素
从上面结果可以发现,要添加的内容已经添加到数组中了。另外还可以采用以下方法:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_164942.jpg?sign=1738983229-AFXnb3b5tRshwtwQnEUy4i8k3JYml1Mu-0-15c7078f0779d703dbb0014ac7cfd8b8)
修改上面示例:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_164943.jpg?sign=1738983229-bILttCrLAxMp0I28tAImGjoWivQZKLT5-0-c69ab980ec03891479edce1dd43337a9)
在浏览器中运行程序,可发现要添加的内容在页面上已经显示,结果如图5-15所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P80_25218.jpg?sign=1738983229-4YsVf7CNYp6SRFUQckUyyQ8l6ZPebzSH-0-ad14b57ad89d4b424634014b4173dbb8)
图5-15 使用数组原型的splice()方法
6.key属性
当Vue正在更新使用v-for渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一key属性。
下面我们先来看一下不使用key属性的一个示例。在【例5.10】中,定义一个nameList数组对象,使用v-for指令渲染到页面,同时添加三个输入框和一个添加的按钮,可以通过按钮向数组对象中添加内容。在示例中定义一个add方法,在方法中使用unshift()数组的开头添加元素。
【例5.10】不使用key属性(源代码\ch05\5.10.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P80_164944.jpg?sign=1738983229-boZyUZaOEHKRZfvR0AbbXWuwfx7h9Gyb-0-dfdee92efb28657745fdd0f6d33e1d4c)
在浏览器中运行程序,选中列表中的第一个选项,如图5-16所示;然后在输入框中输入新的内容,单击“添加”按钮后,向数组开头添加一组新数据,页面中也相应显示,如图5-17所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P81_26096.jpg?sign=1738983229-hPbAExgJ0r4dSo5Ht05TjrwcGNTHTEJ6-0-fbafbaa535bef762627a8627a49ac276)
图5-16 输入内容
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P81_26097.jpg?sign=1738983229-WsCCcQ4vsha2VLS3hmLShnRt9X6ayO6X-0-f22271b585747252c20cd2ee064ed0a5)
图5-17 添加后效果
从上面结果可以发现,刚才选择的“洗衣机”变成了新添加的“电视机”。很显然这不是我们想要的结果。产生这种效果的原因就是v-for指令的“就地更新”的策略,只记住了数组勾选选项的索引0,当往数组添加内容的时候,虽然数组长度增加了,但是指令只记得刚开始选择的数组下标,于是就选择了新数组中下标为0的选项。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一key属性。
修改上面示例,在v-for指令的后面添加key属性。代码如下:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P81_164946.jpg?sign=1738983229-B2ndfHTz9qHELmAgpf8B0JpUUwagOdeO-0-c7896bb9797e91798edc91e2e899d0b2)
此时再重复上面的操作,可以发现已经实现了想要的结果,如图5-18所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P82_26186.jpg?sign=1738983229-jXIMMTcn59XBeuM4WlqoTlxkgEVSOTA8-0-9b0f2d892add1183f05a0bd790806726)
图5-18 使用key属性的结果
7.过滤与排序
在实际开发中,可能一个数组需要在很多地方使用,有些地方是过滤后的数据,而有些地方是重新排列的数组。这种情况下,可以使用计算属性或者方法来返回过滤或排序后的数组。
【例5.11】过滤与排序(源代码\ch05\5.11.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P82_164947.jpg?sign=1738983229-LQ099HTvmUdwWFhQWpE1XRKwvLBLoeKv-0-79aa7cb3186388d079df3b327301ccae)
在浏览器中运行程序,结果如图5-19所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P83_27215.jpg?sign=1738983229-qwRCwrodx4ZEWv8AnrdTmhX5Wmkze0mF-0-8e516ba5719effe6c5d119f6fccce167)
图5-19 过滤与排序
8.v-for与v-if一同使用
v-for与v-if一同使用,当它们处于同一节点上时,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。当只想渲染部分列表选项时,可以使用这种组合方式。
例如【例5.12】所示,循环输出价格大于或等于5000元的商品。
【例5.12】v-for与v-if一同使用(源代码\ch05\5.12.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P83_164949.jpg?sign=1738983229-CdBhclTmMK6qjlK0vc3nNSjBNEWUd7RW-0-1847e4a6b3e7de39fb69559b15d939a5)
在浏览器中运行程序,结果如图5-20所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P84_27993.jpg?sign=1738983229-64YuwIz6Yt3vLrKXE9mVtmnrrZe5RPy1-0-56203629d1b4a6506f1bcb527938810a)
图5-20 v-for与v-if一同使用