从入门到项目实战 - 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 联用

目录
相关文章
|
1月前
|
JavaScript
vue实现任务周期cron表达式选择组件
vue实现任务周期cron表达式选择组件
129 4
|
14天前
|
人工智能 自然语言处理 JavaScript
用 CodeBuddy 搭建Vue框架 像呼吸一样简单
本文介绍如何借助 CodeBuddy 快速创建 Vue 项目。CodeBuddy 是一款支持自然语言编程的工具,能根据用户需求自动生成代码,降低开发门槛。文章详细说明了通过 CodeBuddy 创建 Vue 项目的步骤,包括解决项目创建失败的问题、自动补全代码功能以及启动开发服务器的方法。无论开发者经验如何,CodeBuddy 都能显著提升效率,让开发更专注创意实现。
|
24天前
|
缓存 JavaScript 前端开发
Vue 基础语法介绍
Vue 基础语法介绍
|
2月前
|
JavaScript 前端开发 算法
vue渲染页面的原理
vue渲染页面的原理
145 56
|
2月前
|
SQL JavaScript 前端开发
Vue实现动态数据透视表(交叉表)
Vue实现动态数据透视表(交叉表)
193 13
|
2月前
|
数据采集 资源调度 JavaScript
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
本文介绍了使用 Vue Flow 绘制流程图的方法与技巧。Vue Flow 是一个灵活强大的工具,适合自定义复杂的流程图。文章从环境要求(Node.js v20+ 和 Vue 3.3+)、基础入门案例、自定义功能(节点与连线的定制、事件处理)到实际案例全面解析其用法。重点强调了 Vue Flow 的高度灵活性,虽然预定义内容较少,但提供了丰富的 API 支持深度定制。同时,文中还分享了关于句柄(handles)的使用方法,以及如何解决官网复杂案例无法运行的问题。最后通过对比 mermaid,总结 Vue Flow 更适合需要高度自定义和复杂需求的场景,并附带多个相关技术博客链接供进一步学习。
|
3月前
|
移动开发 JavaScript API
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
|
2月前
|
存储 数据采集 供应链
属性描述符初探——Vue实现数据劫持的基础
属性描述符还有很多内容可以挖掘,比如defineProperty与Proxy的区别,比如vue2与vue3实现数据劫持的方式有什么不同,实现效果有哪些差异等,这篇博文只是入门,以后有时间再深挖。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
3月前
|
JavaScript 前端开发 开发者
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
|
3月前
|
JavaScript 前端开发 数据安全/隐私保护
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。