![Vue.js企业开发实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/909/44509909/b_44509909.jpg)
2.3 列表渲染
2.3.1 遍历元素
当遍历一个数组或枚举一个对象进行迭代循环展示时,会用到列表渲染的指令v-for。v-for指令类似于JavaScript中的for循环,在Vue中提供了v-for指令用来循环数组。
在使用v-for指令时,可以对数组、对象、数字、字符串进行循环,获取其每个元素。在使用v-for指令时,要按照特定的for-in语法进行遍历,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P38_26437.jpg?sign=1739425602-fszlc4FKKr3KyhelEgc5kWYDhmrnmRep-0-dbede448081284a90fa25f164f422554)
在上面的示例代码中,items是源数据数组,item为每次迭代遍历的数组元素,index为元素在数组中的索引。
1.遍历数组
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P38_26440.jpg?sign=1739425602-oqhpUxEXPbBdsMyGXKQv7DJVcEJJTz5D-0-60bacb3a5bd12c7f56a0d7c37a3a72e7)
在浏览器中运行的效果如图2.14所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_4996.jpg?sign=1739425602-c8anRiV3VQEsaEkn08bddFFIpQhYoHrr-0-2dea0f23309b3fa3203a3b8a6e6c3274)
图2.14 遍历数组效果
在v-for指令中,可以使用of替代in作为分隔符,因为它更接近JavaScript迭代器的语法,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_26441.jpg?sign=1739425602-z34BPxpg0nRLjdsvk5TnWaJXmxZ1iBwB-0-f922f19e7495595d49ebe4ef7c197795)
2.遍历对象
v-for指令不仅可以遍历数组,还可以用来遍历对象,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_26442.jpg?sign=1739425602-MYjFI3Ac7fqu7dHtZdT9GD50kTG9Po4O-0-637b78817c6d342e84de15daad9eff56)
在上面的示例代码中,使用v-for循环迭代出来的元素有两个参数,第一个参数为对象属性的值,第二个参数为对象的属性。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_26443.jpg?sign=1739425602-DyaC3qm3oy0iBr0DJ6UwVz7HGwT9fu4I-0-9a555b2f93b2a7fc4f309bb934957f19)
在浏览器中运行的效果如图2.15所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_5102.jpg?sign=1739425602-oNj7W3MB1yUsKn4WgNjeM2Q3uDrPTcrN-0-ee8ea1d80a7e2339e5ec41c1a1705a42)
图2.15 v-for的遍历对象
使用v-for指令遍历对象时,迭代的元素使用第3个参数作为索引,在上面的代码中添加第3个参数,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_26444.jpg?sign=1739425602-Uxqw2FjCB1IhRvvUH7cpwm8ZVFGIlIBp-0-f28f658c4c7d70792fef09e169001d7d)
在浏览器中运行的效果如图2.16所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_5138.jpg?sign=1739425602-zm6BCgxFJm5YRxpUp5X8Bd8SoWefPF1X-0-004e39341bdbe1448ec449eb825c9d4b)
图2.16 v-for的第3个参数(索引)
3.遍历整数
v-for还可以直接遍历整数,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_26445.jpg?sign=1739425602-AHhRSA7MKd4lOYcQnp6qIdVMjZIquska-0-ad73d54a541ad632665a19c0545b9c81)
在浏览器中运行的效果如图2.17所示。
2.3.2 维护状态
当Vue正在更新使用v-for渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置被正确渲染。这类似于Vue 1. x的语句track-by="$ index"。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P41_5193.jpg?sign=1739425602-KHrDaHtFz1Ccakm8yht43dW0TDoOj88l-0-851b0925ac613faa75a26cc1d75d89cb)
图2.17 v-for遍历整数
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如:表单输入值)的列表渲染输出。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一key属性,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P41_26446.jpg?sign=1739425602-nqfZfCKLoQN91bTpwTFozunT3oprLPdS-0-b09607d28c0c89ac846d7b67acece10c)
建议尽可能在使用v-for时提供key属性,除非遍历输出的DOM内容非常简单,或者刻意依赖默认行为以获取性能上的提升。
注意 不要使用对象或数组之类的非基本类型值作为v-for的key,而要使用字符串或数值类型的值。
2.3.3 数组更新检测
Vue为了增强列表渲染功能,增加了一组观察数组的方法,并且可以显示一个数组的过滤或排序的副本。
1.变更方法
Vue将被侦听的数组的变更方法进行了包裹,所以它们也会触发视图更新。这些被包裹过的方法如下。
(1)push():接收任意数量的参数并逐个追加到原数组末尾,返回新数组的长度。
(2)pop():移除数组最后一项,返回被移除的元素。
(3)shift():移除数组的第一项,返回被移除的元素。
(4)unshift():在数组前追加新元素,返回新数组长度。
(5)splice():删除指定索引的元素,并且可以在该索引处添加新元素。
(6)sort():对数组进行排序,默认按字典升序排序,返回排序后的数组。
(7)reverse():用于反转数组的顺序,返回反转后的数组。
这些方法类似于JavaScript中操作数组的方法。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P42_26456.jpg?sign=1739425602-2xNZvZnV4s7sdLFaBSgZP4djkxs2lF65-0-dec4fc8b721d74efe5230d90ca4ae1f7)
在浏览器中运行的效果如图2.18所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P42_5296.jpg?sign=1739425602-eyQhJmEI7XMUE0y7ra13zM7TKZeeg30Z-0-7064aa873671c627ecb1180271e1f5ad)
图2.18 push()方法的执行效果
2.替换数组
变更方法,顾名思义,会变更调用这些方法的原始数组。相比之下,也有非变更方法,例如filter()、concat()和slice()。它们不会变更原始数组,而是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组。
非变更方法如下。
(1)concat():创建当前数组的副本,然后拼接参数中的数组,返回拼接后的新数组。
(2)slice():将数组的索引作为参数,可从已有的数组中返回选定的元素,返回新数组。
(3)map():对数组的每一项运行给定函数,返回每次函数调用的结果所组成的数组。
(4)filter():对数组的每一项运行给定函数,该函数会返回值为true的项所组成的数组。
非变更方法也和JavaScript中的方法类似。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P42_26457.jpg?sign=1739425602-lbZNc3l0PIlyT7NFw4EkiqffZoBFTZ7d-0-f80b9e86c92ab096241aa1000c6cd4f4)
在浏览器中运行的效果如图2.19所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P43_5377.jpg?sign=1739425602-gnrq4cbir5kqx9EbewmH9qCMDSizoGes-0-ae1b6ffb8148aef120182b7b38dc7f4c)
图2.19 filter()方法的执行效果
在上面的代码示例中,要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据(使用非变更方法),可以使用filter()方法。
2.3.4 对象变更检测注意事项
由于JavaScript的限制,Vue无法检测对象属性的添加或移除。由于Vue会在初始化实例时对属性执行getter/setter转化,所以属性必须在data对象上存在才能让Vue将它转换为响应式的,这是由Vue的双向数据绑定决定的。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P43_26459.jpg?sign=1739425602-KiWf3lBsCYsxcqh2Ryg3S3oSrDK5T1Ul-0-447c7439e7ce66d4bdba0bb0b2419ce6)
在上面的示例代码中添加的age属性不是响应式的,所以在页面中不会被渲染出来,在浏览器中运行的效果如图2.20所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_5448.jpg?sign=1739425602-nsPSR91o5kGzipTQR1R9OWnWI00gNtgq-0-4864d0dc9bc9707dbaae41a19ece13f9)
图2.20 添加非响应式属性的效果
对于已经创建的实例,Vue不允许动态添加根级别的响应式属性。但是,可以使用Vue.set(object,propertyName,value)方法向嵌套对象添加响应式属性,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_5460.jpg?sign=1739425602-BxRhq9h3jYa6I2g7iUxZGfspU2V9RQvG-0-43756c1d51bee21e8a42d9207adc6fc3)
我们可以使用上面的示例代码,为Vue实例中的对象添加响应式属性。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_26461.jpg?sign=1739425602-p21ChXVy11SwBQnN0fW5YmTjzu1sejHn-0-b19d209bc79153dccf3dfc4df403a5be)
在浏览器中运行的效果如图2.21所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_5503.jpg?sign=1739425602-pei06DQ6ZqGyvv8AWlcTWm30PcNsXP4x-0-17765a02fb357270a41c4e8655fc26ff)
图2.21 添加响应式属性效果
除了上面的方法,还可以使用vm. $ set实例方法添加响应式属性,它只是全局Vue.set的别名,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P45_5526.jpg?sign=1739425602-nV1hDiRNwzlQAJWJWAEKtCo1vCLe7xwC-0-eac6791228cdc2737e9583a39b06ffbe)
有时可能需要为已有对象赋值多个新属性,例如使用Object.assign()或_.extend()。但是,这样添加到对象上的新属性不会触发更新。在这种情况下,应该用原对象与要混合进去的对象的属性一起创建一个新的对象,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P45_26462.jpg?sign=1739425602-UM4wXZABtM7pBqmgodK9tH6mlrZFi6X8-0-4585e1e3b6f89665be538faaa1d31355)
2.3.5 在<template>上使用v-for
类似于v-if,也可以利用带有v-for的<template>来循环渲染一段包含多个元素的内容。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P45_26463.jpg?sign=1739425602-p6cUpxV6DcPAzGoYSjmnYk2sm4nNY7i4-0-50d637aaa6d157077d891990cd2489b7)
在浏览器中运行的效果如图2.22所示。
template中可以放执行语句,最终编译后不会被渲染成元素。一般常和v-for指令及v-if指令结合使用,这样会使整个HTML结构没有多余的元素,从而使整个结构更加清晰。
2.3.6 v-for与v-if一同使用
当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。当只想为部分项渲染节点时,这种优先级的机制十分有用。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P45_26464.jpg?sign=1739425602-LkssZk9AsU6ToiR6D8IB6JLH8YrUsxMx-0-58c6363f18da235040422a29cbcb101c)
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P46_5682.jpg?sign=1739425602-OByPVrlTKcOkVgK8POV8PTaFTLhRIinB-0-ab62bf0a0180bb9b41f62c92209e5eea)
图2.22 DOM渲染结果
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P46_26465.jpg?sign=1739425602-xc34eq9h9I1nZiL5wK3cyOJwRyth9xy0-0-5f7b3c5a298f7c5a2810652feb0afc69)
在浏览器中运行的效果如图2.23所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P46_5724.jpg?sign=1739425602-xWWdcfOSvFq75iCweD1KNLn37juLNiYM-0-c814ce25b3f29d1d0d15fcf4261f1c19)
图2.23 v-for与v-if一起使用的效果
注意 不推荐在同一个元素上使用v-for和v-if,必要情况下应该替换成计算属性computed。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P47_26574.jpg?sign=1739425602-5BrqGVIAL5aPp2QIvAp8zuWf21GyQ2MW-0-546acd87af89a369e330a03559c0f79c)
在浏览器中运行的效果如图2.24所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P47_26561.jpg?sign=1739425602-IFLI4bUB9VnWP2VR1kNIlLgdxsZqhlLd-0-9e224663ca367eb9dcb51fbec6e5e144)
图2.24 计算属性实现效果