从入门到项目实战 - Vue 列表渲染

简介: 从入门到项目实战 - Vue 列表渲染


Vue 列表渲染



1. 列表渲染基础

1.1 什么是列表渲染

列表渲染是一种将一个数组、字符串、对象、数字以一定的方式展开成多个项目渲染到页面上的方式。

1.2 基本用法举例

1.2.1 数组

<ol>
  <li v-for="(item, index) in ['A', 'B', 'C']">item = {{ item }}, and index = {{ index }}</li>
</ol>

其渲染效果为:

注意:

  • 使用 v-for ... inv-for ... of 都可以,它们没有区别。(后文不在赘述)

1.2.2 数字

v-for 可以直接接受一个整数值,这相当于接受一个从 1 开始到该整数的数组。例如:

<ol>
  <li v-for="(number, index) in 3">number = {{number}}, and index = {{index}}</li>
</ol>

其渲染效果为:

注意:

  • index 和 所遍历项的数字在值上看,总是index比遍历项少1,因为 index 是从 0 开始计算而遍历项是从1开始算的。

1.2.3 字符串

v-for 指令可以遍历一个字符串。例如:

<ol>
  <li v-for="(item, index) of str">item = {{ item }}, and index = {{ index }}</li>
</ol>

其渲染效果为:

1.2.4 对象

v-for 指令在遍历一个对象时,将使用 JavaScript 对象的 属性名(键)作为遍历时的 index,使用 与该 属性名 对应的 作为遍历项,例如:

<ol>
  <li v-for="(item, index) of { J: 'ack', B: 'ush', A: 'lice' }">index = {{ index }}, and item = {{ item }}</li>
</ol>

其渲染效果为:

1.2.5 集合(Set)

集合(Set)是 ECMA Script 6 中定义的一个存储任何类型的唯一值的类型,它最常用于对一个数组进行去重。比如:

const s = new Set(["张三", "李四", "王五", "李四", "王五"])
console.log(s);
console.log([...s]);

Out[]:

{ "Set(3)": [ "张三", "李四", "王五" ] }
[ "张三", "李四", "王五" ]

使用 v-for 遍历一个集合的例子如下:

const s = new Set(["张三", "李四", "王五", "李四", "王五"])
<ol>
  <li v-for="(item, index) of s">item = {{ item }}, and index = {{ index }}</li>
</ol>

其渲染效果为:

1.2.6 映射(Map)

提示: 在编程语言中的 Map 含义不是地图,而是映射,这也是该单词最原始的含义。

映射(Map)是 ECMA Script 6 中定义的一个用于存储键值对的类型,任何值(对象或者基本类型)都可以作为一个键或一个值。虽映射像对象那样,具有键值对的使用形式,使用 v-for 遍历一个 映射 与遍历一个数组的不同之处在于,遍历映射时将以从 0 开始的整数索引值作为 index,使用 [key, word] 形式的数组作为遍历项。例如:

const m = new Map()
m.set('张', '三');
m.set('李', '四');
m.set('王', '五');
<ol>
  <li v-for="(item, index) of m">item = {{ item }}, and index = {{ index }}</li>
</ol>

其渲染效果为:

2. 数组渲染进阶

2.1 列表渲染中的 key 属性

2.1.1 key 属性于虚拟DOM 的更新规则

key 是 vue 中虚拟 DOM 所使用的对象标识,当数据发生变化时,Vue 会根据 新数据 生成 新的 虚拟 DOM,然后对从上到下从外到内从左到右对虚拟DOM进行扫描,对于某一个虚拟DOM,新的虚拟 DOM 与 旧的虚拟 DOM 进行差异比较。比较方式为:

  • 先比较新旧虚拟 DOM 的 key 属性:
  • 如果新的虚拟DOM中key 不存在与 旧的虚拟DOM中,则:
    将该新的虚拟 DOM 更新到内存做为新的虚拟DOM,同时渲染到页面为新的真实DOM。
  • 如果新的虚拟DOM的 key 属性值存在于 旧的虚拟DOM 中,则:从前到后比较该虚拟DOM的所有内容(子元素)。
  • 如果内容没变,则:直接使用旧的虚拟DOM。
  • 如果内容改变,则在内容改变处更新虚拟DOM,将将其渲染为新的真实DOM。
  • 对于内容的内容依次方式递归处理。

2.1.2 省略 key 时可能出现的问题

很多时候的确不写 key 属性也能实现我们需要的效果,比如:

const data = ["尔康", "尔泰", "紫薇", "小燕子"];
<ul>
  <li v-for="(item, index) in data">{{ item }}</li>
</ul>

虽然我们没有指定key属性,但是效果依然可以正常渲染:

然而

2.1.3 使用 index 作为 key 可能出现的问题

多数情况下我们的确可以直接使用 index 作为 v-for 遍历所需的 key 使用,例如给定一个三级手风琴目录数据如下:

const menu = [
  { title: "一级目录1", childern: [
      { title: "1-1" },
      { title: "1-2" },
    ]
  },
  { title: "一级目录2" },
  { title: "一级目录3", childern: [
      {
        title: "3-1", childern: [
          { title: "3-1-1" },
          { title: "3-1-2" },
        ]
      },
      { title: "3-2" },
    ]
  }
]

我们对数据逐层进行展开:

<ul>
  <li v-for="(menu1, index1) in menu" :key="index1">
    <p>{{ menu1.title }}</p>
    <ul v-if="menu1.childern">
      <li v-for="(menu2, index2) in menu1.childern" :key="index2">
        <p>{{ menu2.title }}</p>
        <ul v-if="menu2.childern">
          <li v-for="(menu3, index3) in menu2.childern" :key="index3">
            <p>{{ menu3.title }}</p>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

其渲染效果为:

在 2.1.1 节中我们知道

2.1.4 开发中如何选择 key

在上面,我们讨论了两种和虚拟DOM有关的问题:

  1. 若列表渲染中存在逆序增减项目等类似 破环原先渲染项顺序 的更新行为:
    将产生没有必要的真实DOM更新,降低页面渲染效率。
  2. 若列表渲染中,渲染项还包含了表单。在破环顺序的曾减项时:
    将导致表单错位等意外情形发生。

在 Vue 中,key 属性是用于给 vue 框架标识虚拟DOM用的。为了避免上述非预期情况的发生,我们应该 使用能够唯一标识每条数据的值作为数据项们的 key 属性值。通过这种方式:

  1. 对于逆序增减等破坏顺序的操作:
    由于 key 属性标明了各条数据的唯一标识,Vue 能够正确识别后面没有改动的DOM,不会对这些不需要改动的 虚拟DOM 对于更新渲染到 真实DOM。
  2. 对于不仅破坏顺序,而且存在表单的情形:
    由于Vue能够正确唯一识别每一条 虚拟DOM 项,一旦虚拟DOM变化,Vue不会去检查包含表单子项的改动。这些表单往往又是有状态的,即当用户在真实DOM的表单上改变了这些表单值时,虚拟DOM却不会改变,Vue也不会知道这些变动。
    通过人为地添加每项地唯一标识 key,Vue不再需要检查子项内容而错误更新,直接更新破坏顺序增减地整项,就避免了这种更新错乱地行为发生。

因此 找到能够唯一标识每条数据的值作为数据项们的 key 属性值 就成了提高渲染效率、避免更新错误地关键。那么采用什么作为列表渲染中数据项地 key 呢?

一般在实际开发中,合格地后端都需要给前端返回一个每条数据的唯一标识,这个标识往往能在 数据库 中唯一的确定该条数据,这样不论什么时候从后端请求跟新的新数据都能够唯一识别这条数据。比如,在一个标识用户信息的数据表中,昵称往往是重复的,用户id是唯一的,那么就可以使用用户id作为key。

2.2 避免同一个元素上与 v-if 联用

目录
相关文章
|
29天前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
1月前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
|
5天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
37 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
29 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章
|
1月前
|
JavaScript 前端开发 算法
vue学习第7章(循环)
欢迎来到瑞雨溪的博客,一名热爱JavaScript和Vue的大一学生。本文介绍了Vue中的v-for指令,包括遍历数组和对象、使用key以及数组的响应式方法等内容,并附有综合练习实例。关注我,将持续更新更多优质文章!🎉🎉🎉
25 1
vue学习第7章(循环)
|
1月前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
30 1
vue学习第九章(v-model)
|
1月前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
42 1
vue学习第十章(组件开发)
|
1月前
|
JavaScript 前端开发
vue学习第十一章(组件开发2)
欢迎来到我的博客,我是瑞雨溪,一名自学前端两年半的大一学生,专注于JavaScript与Vue。本文介绍Vue中的插槽(slot)使用方法,包括基本插槽、具名插槽及作用域插槽,帮助你在组件开发中实现内容的灵活定制。如果你觉得有帮助,请关注我,持续更新中!🎉🎉🎉
23 1
vue学习第十一章(组件开发2)