![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=1739334006-laHibf65RlsKeDaUl7h5E989kW8sM3kD-0-c303d924476b85cd6d60328bd5f61dd1)
在上面的示例代码中,items是源数据数组,item为每次迭代遍历的数组元素,index为元素在数组中的索引。
1.遍历数组
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P38_26440.jpg?sign=1739334006-oRj4J9AgpG7kQ9jpwoZRg4qhHXgpQ0a0-0-31340e787376b30299918626a0ee3366)
在浏览器中运行的效果如图2.14所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_4996.jpg?sign=1739334006-csvYXB86nhyYEuE6fpuse7zYUlVakasc-0-89ef64ba60e9822de4d631565c4b0dcb)
图2.14 遍历数组效果
在v-for指令中,可以使用of替代in作为分隔符,因为它更接近JavaScript迭代器的语法,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_26441.jpg?sign=1739334006-b8nmtVRZ7I7shFB4EgV5IGWdxsg4UPVD-0-91b8201fa39448f45bb9311b371517df)
2.遍历对象
v-for指令不仅可以遍历数组,还可以用来遍历对象,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_26442.jpg?sign=1739334006-Kiw6lUpgGIymh45mILmtwSr6GhvwJ9MS-0-9ba7ff2a71827b8b04dcf2ab2c10b5a4)
在上面的示例代码中,使用v-for循环迭代出来的元素有两个参数,第一个参数为对象属性的值,第二个参数为对象的属性。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P39_26443.jpg?sign=1739334006-UgLFGJGD9V6HY21Afay7P61a1XL8QmQD-0-94098c87e751e93a4bc190186c50372e)
在浏览器中运行的效果如图2.15所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_5102.jpg?sign=1739334006-vMmG9dCm01JGpFtUyEyGEYntI73OF5tQ-0-2337a29670ae26bab6484e92be660fc7)
图2.15 v-for的遍历对象
使用v-for指令遍历对象时,迭代的元素使用第3个参数作为索引,在上面的代码中添加第3个参数,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_26444.jpg?sign=1739334006-cruAUjsMAdUfKXp3F69zvX7ogsmYDIxY-0-5f3406642fee2a4ffb92e24ffb830196)
在浏览器中运行的效果如图2.16所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_5138.jpg?sign=1739334006-Oygb1bJ80PCQE5msm1yDnAQkA5LPQlPB-0-dd2fef9c33cfb326af6c55566db11ca5)
图2.16 v-for的第3个参数(索引)
3.遍历整数
v-for还可以直接遍历整数,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P40_26445.jpg?sign=1739334006-Vt5ogpnsniiKGFlDX4oggi6RhE3Ninzi-0-99d555e71f6c940220089d082195f847)
在浏览器中运行的效果如图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=1739334006-NLolf2FAtAfFPuOqZ3haVHGdQsbWeEak-0-2dee91e526ccb2087f0af3e3b6cc8021)
图2.17 v-for遍历整数
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如:表单输入值)的列表渲染输出。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一key属性,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P41_26446.jpg?sign=1739334006-rJuJUoD1WWFV5HNKL47DAvEYC0zlmvU0-0-c6d911936d73e47588c6a6f652e20a3a)
建议尽可能在使用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=1739334006-ZqIyzVFucNK42Tl5HYiJsalZIlDA4NfC-0-218863dfede97b415bf735596b83b301)
在浏览器中运行的效果如图2.18所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P42_5296.jpg?sign=1739334006-T9uGfGrHGBeepvNvFKpSqFPtKlkZ5No4-0-821058c91dcb18c77e45d3cbd1dcaf1b)
图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=1739334006-EIfXp8E7z5WlL9iEDHnEnoroWAKWqCBI-0-aa0c172fd14f110b27bbb13296a7e280)
在浏览器中运行的效果如图2.19所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P43_5377.jpg?sign=1739334006-LrAWV75fAFUYpwZ26PZ5f1u4D7UAkSyU-0-92fa0b81b12fd65160223b03b5e8da97)
图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=1739334006-00dndy4WpVbi6yubjR4ZQaRUtGamgxHS-0-e8b71e5ab08d864da98035a33e528bf3)
在上面的示例代码中添加的age属性不是响应式的,所以在页面中不会被渲染出来,在浏览器中运行的效果如图2.20所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_5448.jpg?sign=1739334006-4Ccla7yxqGWnsTbdCh1Z3vdPTSGUyCvg-0-f0a3b69d24822bb851c94c511ee63ce2)
图2.20 添加非响应式属性的效果
对于已经创建的实例,Vue不允许动态添加根级别的响应式属性。但是,可以使用Vue.set(object,propertyName,value)方法向嵌套对象添加响应式属性,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_5460.jpg?sign=1739334006-xHQHRNJpjv4gnprkq8HIVXbi4JgN2461-0-659796ca7583052fbcee6a441bc115ff)
我们可以使用上面的示例代码,为Vue实例中的对象添加响应式属性。
index.html文件代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_26461.jpg?sign=1739334006-H83xvx0CHhEDhfH0oLPPnDSbzr6tquIF-0-33fcfadfd37b4f9198c6508eda03cc2d)
在浏览器中运行的效果如图2.21所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P44_5503.jpg?sign=1739334006-FqXwXiGMfkjVTnWT6SybcNi1PmNlhwKX-0-f3290e477703f208b782c0a6f086bf3a)
图2.21 添加响应式属性效果
除了上面的方法,还可以使用vm. $ set实例方法添加响应式属性,它只是全局Vue.set的别名,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P45_5526.jpg?sign=1739334006-ygTelSqlXzsSWWvXtYKKVQNuSq6udSy9-0-677dcdf567e5de2a30c54d991fe1feb6)
有时可能需要为已有对象赋值多个新属性,例如使用Object.assign()或_.extend()。但是,这样添加到对象上的新属性不会触发更新。在这种情况下,应该用原对象与要混合进去的对象的属性一起创建一个新的对象,代码如下:
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P45_26462.jpg?sign=1739334006-p03lYkunsU9LuXMEBm51ctcnM2LgPuUH-0-608d123738317dd547f9f672fb292054)
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=1739334006-JNGmzFPFPM2PWge97H8mCrRrllHpNUYS-0-698c5d4797a29b5f2ce3d037dec2fd1b)
在浏览器中运行的效果如图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=1739334006-oqGK4ysmr4uDWS0UJaPCpmI4Svcofs4U-0-0b8e4d794a25312579cbd603086e13a5)
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P46_5682.jpg?sign=1739334006-bhb11QTp221c8GmotocYj6em93itvd75-0-8d3e7c643c8a711f6e5fad67645ef27a)
图2.22 DOM渲染结果
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P46_26465.jpg?sign=1739334006-HvtACD8RcWCQAemcJ1KnrL07oeMp28p0-0-42a7c552c1a73d108a0775dd2b695619)
在浏览器中运行的效果如图2.23所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P46_5724.jpg?sign=1739334006-IvdVZ38LiqeVPDeyyATlxbCE2N6oam7A-0-8c33fa3deccbf7d214dcf10e0889f5b6)
图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=1739334006-Ezq8rDmsoH5DBwi1FNJzXh0RuVIOIExk-0-39bd56c5fb0316d8311239bcee51e9d1)
在浏览器中运行的效果如图2.24所示。
![](https://epubservercos.yuewen.com/85E887/23721628409520006/epubprivate/OEBPS/Images/Figure-P47_26561.jpg?sign=1739334006-7Hc7Rt3FPJ3GhsdVuQrIWR9l2svAGe4P-0-a8a6c603304e60d3ed02e5d37417b34c)
图2.24 计算属性实现效果