- Vue.js 3.0从入门到精通(视频教学版)
- 李小威编著
- 2198字
- 2022-07-27 18:37:47
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=1739006095-jLC2ZLciMZHgOpSO8K0cZjrZbTNgsJtl-0-34e853b764198b00889f0476a72c84b3)
下面看一个示例,使用v-for指令循环渲染一个数组。
【例5.4】v-for指令遍历数组(源代码\ch05\5.4.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P73_164931.jpg?sign=1739006095-TOXwVY7uAVLv2zrs7AUxRkwevxz3Uz5k-0-54746c7ef6a46f6dd179d773176d44ec)
在浏览器中运行程序,按F12键打开控制台并切换到“Elements”选项,结果如图5-5所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P73_22306.jpg?sign=1739006095-voJvQnrm2HN7HOC5mcK5Wbam64lllssI-0-c1511601e1a385a7b549f086676d0bcf)
图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=1739006095-qz4nKQULXJ574dG0bRVj051fM5vLvOT9-0-2638b23b0ed521d14dc789286659e9ae)
在浏览器中运行程序,结果如图5-6所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_22434.jpg?sign=1739006095-4Lgz7DyjhELBlS6iFpZpZGRStBCFhhhh-0-fa291709c9d5ffd14bf4a5fe1b70298a)
图5-6 v-for指令第二个参数
2.v-for指令遍历对象
遍历对象的语法和遍历数组的语法是一样的:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_165357.jpg?sign=1739006095-x5fIalOLio9TgGURMCBnhL3Wg6bPWSIM-0-8439db9098ddddc8fb56eb5404e5558e)
其中object是被迭代的对象,value是被迭代的对象属性的别名。
【例5.5】v-for指令遍历对象(源代码\ch05\5.5.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P74_164933.jpg?sign=1739006095-XiuMlKWicdcJh22HTA4Ssf7O42HKWS0r-0-70a8dd7392a887422906d47ebb0ec1fe)
在浏览器中运行程序,结果如图5-7所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P75_22948.jpg?sign=1739006095-fvYv5ftjO6gldPSKBMRwCBjQ0dws0mAl-0-6ebdc932a8b1071aa02f64e2410fb549)
图5-7 v-for指令遍历对象
还可以添加第二个参数,用来获取键值;获取选项的索引,可以添加第三个参数。
【例5.6】添加第二、三个参数(源代码\ch05\5.6.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P75_164935.jpg?sign=1739006095-4tJcOshKnhxfPJVFdv3fwJtWXUMNk070-0-69a2de5e8ae45e3a6aefbf9756660fb7)
在浏览器中运行程序,结果如图5-8所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P76_23436.jpg?sign=1739006095-fPWtYRt0dN47Ejngia2QwHsgkrrgpwMo-0-706c092d758b6b7496c7bd056bebdaf5)
图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=1739006095-58t363zgu4fXAtipiNVtLM0GUSyDAbK4-0-90771ebcf2b37ce37f8ad02617707ff5)
在浏览器中运行程序,结果如图5-9所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P76_23701.jpg?sign=1739006095-OzXxrlXmXDj9SpM9ni1b6yEFWwtFl0mu-0-adcb072640de391b752350ba9ceec81f)
图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=1739006095-MYlvTZalRMoGTULJTgbWAlVA6MEPLrUI-0-675c430a9b08a97d1987d6bb4e4d7162)
在浏览器中运行程序,按F12键打开控制台并切换到“Elements”选项,并没有看到<template>元素,结果如图5-10所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P77_24142.jpg?sign=1739006095-VeIu8zeAtgUna0vwLg2yilbYp4w7TLkn-0-9cd7786b9b83006bd617cec978a28131)
图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=1739006095-2T0Gbpw4aKRVZPvL354UOK9QjxCVWUsK-0-c07fc29fda31ee1b629fb93d403edcc2)
在浏览器中运行程序,结果如图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=1739006095-R8I1eL55k5Vg9AoBZk1jz9lR3p0wt28m-0-94bdcf696177b1de1d6b6d31d78e267a)
图5-11 初始化效果
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P78_24563.jpg?sign=1739006095-45LklVAT2gWRmYWftt7WCitQ3gbe51Tk-0-d78b874c76c0709ee2cd21982d11c5d3)
图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=1739006095-ldmfJPz1R07QZLUcRtOBVQIvFD0VJu8T-0-be41c7cf2729460506d8b33b0174a3e3)
图5-13 使用新数组替换原始数组
可能会认为,这将导致Vue丢弃现有DOM并重新渲染整个列表,但事实并非如此。Vue为了使得DOM元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组,这是非常高效的操作。
在Vue 3.0版本中,可以利用索引直接设置一个数组项,例如修改上面示例:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_164941.jpg?sign=1739006095-klyg5gjtuPJD0YsRQPZHoosUSS6H48Rl-0-28af4fac0b12282acb0d1b99874e14a3)
在浏览器中运行程序,结果如图5-14所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_24878.jpg?sign=1739006095-Eb4hpFLgAPqwv1zcCNMDpMNZXIETrcGH-0-16839d316664a3e7610c03b8e5bb2935)
图5-14 通过索引向数组添加元素
从上面结果可以发现,要添加的内容已经添加到数组中了。另外还可以采用以下方法:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_164942.jpg?sign=1739006095-DoaLjNHvYKBkMx1x9mMkdv4pk0ZN6m73-0-7c63be25cff574f3143d01b0d4547bf5)
修改上面示例:
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P79_164943.jpg?sign=1739006095-hyM4mDqxvXRz5ZAkfjn9p2AH5MBgsdfJ-0-7ef71be675db997cbd75808ed5144442)
在浏览器中运行程序,可发现要添加的内容在页面上已经显示,结果如图5-15所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P80_25218.jpg?sign=1739006095-fYtMgqtn0pGCFyVX5vSvIGiHcu3ZETzy-0-10f23ab87daf82392c1f947dddb9075f)
图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=1739006095-W5ymHHzVQ8x2RaI2NWySjT2lnbs2aKOY-0-a41f7f70d05031c6de1f4328e7624691)
在浏览器中运行程序,选中列表中的第一个选项,如图5-16所示;然后在输入框中输入新的内容,单击“添加”按钮后,向数组开头添加一组新数据,页面中也相应显示,如图5-17所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P81_26096.jpg?sign=1739006095-2q6i3FRcU2reWEM2BTpgpfXYV8I6yXdK-0-f729ee687aca5783b06d8a4e31666ab3)
图5-16 输入内容
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P81_26097.jpg?sign=1739006095-M6HFvK4JNpvJ2p7inXrkLOP71bLIVWs5-0-68d4802b64913dd13659ffb89ccd5b6c)
图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=1739006095-Tp11yDJKCJfSX1WzJorqnfLCpN8gL7IU-0-c016d813e47b860e27bbd39b68d91504)
此时再重复上面的操作,可以发现已经实现了想要的结果,如图5-18所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P82_26186.jpg?sign=1739006095-lrKUX55zHCH1QHpizeo5nBkHQsoAv1Rn-0-3f4c53f0885074f4f340720f56dca491)
图5-18 使用key属性的结果
7.过滤与排序
在实际开发中,可能一个数组需要在很多地方使用,有些地方是过滤后的数据,而有些地方是重新排列的数组。这种情况下,可以使用计算属性或者方法来返回过滤或排序后的数组。
【例5.11】过滤与排序(源代码\ch05\5.11.html)。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P82_164947.jpg?sign=1739006095-zjLpWCGZJVlu3i8rsFlMPfpaerxfHZno-0-1e8c93b7bd2429fd2a56c611195c3568)
在浏览器中运行程序,结果如图5-19所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P83_27215.jpg?sign=1739006095-Y9Bcv0i6kwqyIG7NIsfSACixibtS59ae-0-0aef825e32984577320bcdfce8c0b008)
图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=1739006095-Ph1fPi0Z0mSCUvnnDelrBtSUDiv1ni7I-0-26824a1543d2f6abbf9b7ea63d89a282)
在浏览器中运行程序,结果如图5-20所示。
![](https://epubservercos.yuewen.com/AF1F26/23721640501031706/epubprivate/OEBPS/Images/Figure-P84_27993.jpg?sign=1739006095-3qvox1X868rkffqV62GU0ANbAoVIYts1-0-c69226e5983da074b23f8c4919d45952)
图5-20 v-for与v-if一同使用