Vue 的列表渲染
在使用Vue构建项目的过程中,鄙人体会良好印象颇深的 Vue 特色功能有不少,其中用起来最顺手的一个功能就是 Vue 可以非常方便地进行列表渲染,一键批量构筑形如ul>li*10
这样的 HTML 标签列表。用术语的话就叫做列表渲染。
曾经过于小白然而头铁的我,试着用原生HTML, CSS, JS的笨办法来仿写一个某电商网页。遇到的第一道难关就是铺天盖地的 uk>li
标签海,海量的数据,海量的属性,犹如地狱,让我无所适从。不仅是innerText
内容每一条都要录入,还有各不相同的class
等属性,当时的我直接放弃治疗克隆了 n 胞胎 li 占位来充数。之后在使用原生 JS 对HTML节点进行绑定和管理时,也是无比痛苦的。
当时的我就想着,市面上一定是有成熟的一套指令库,帮前端工程师做好这些纯纯又蠢蠢的重复体力劳动。应该我直接输入一个 text 数组,一个 attributes 数组它就会直接帮我建立起一套对应的uk>li
标签库。果不其然,刚刚上手 Vue 就体会到了它的好,它的 v-for
列表渲染功能非常符合我的预期。
用 v-for 把一个数组对应为一组元素
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in array
形式的特殊语法,其中 array
是源数据数组,而 item
则是被迭代的数组元素代称。这两个命名并不固定,array
需要对应父元素传递的 props 属性名,而item
则是自行命名即可。
<ul class="do-list">
<li v-for="item in array" :key="item.value"> {{ item.value }} </li>
</ul>
new Vue({
el: '#example-1',
props: { array: Array }
// array = [ { value: 'aaa' }, { value: 'bbb' }...]
})
这样就得到了一整列用一个对象数组就规定了 text 内容和 attribute 属性的 ul 列。
这里你可能会注意到了在模板标签中这个attribute的存在,实际上,使用v-for
指令必须绑定key
的值,否则 Vue 就会给你报错。所以这个key
到底是什么东西呢。
先别着急,先看看v-for
指令另一个支持的可选参数形式:
<ul class="do-list">
<li v-for="(item, index) in array" :key="index"> {{ item.value }} </li>
</ul>
index 即当前项 item 在数组中的的索引。奇怪,这个key
的值怎么又可以绑定到 index 了。
那么接下来就要探究下绑定的 key
这个奇怪的 attribute 到底是什么东西。在聊它之前,不得不涉及到的知识点有,Vue是如何实现托管元素的状态维护的。
状态维护
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
attribute。
因为它实际上是 Vue 识别节点的一个通用机制,key
并不仅与 v-for
完全绑定。
key atrribute
key 预期:number | string | boolean | symbol
key
这一特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
最常见的用例是结合 v-for
指令进行列表渲染。
但它也可以用于强制替换元素/组件而不是重复使用它。如下场景它可能会很有用:
- 完整地触发组件的生命周期钩子
- 触发过渡
<div> <span :key="text">{{ text }}</span> </div>
当text
发生改变时,<span>
标签总是会被进行替换而不是被修改,因此会触发过渡动画。
通过以上这些例子,至此你就对于v-for
指令,以及该指令中要求的 key
绑定有了新的理解。
部分内容引自 Vue 2 官方文档。