Vue 列表渲染详解_vue 渲染table

Vue 列表渲染详解_vue 渲染table

编码文章call10242025-09-22 15:45:531A+A-

v-for 基本用法

v-for 是 Vue 中用于基于数组渲染列表的核心指令,它的基本语法是 item in items,其中:

  • items 是源数据数组(响应式数据)
  • item 是当前迭代项的别名,用于在模板中访问当前项的数据

示例代码

 // 定义响应式数组
 const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
 <!-- 模板中使用 v-for 渲染列表 -->
 <li v-for="item in items">
   {{ item.message }}
 </li>

索引与父作用域访问

v-for 支持第二个可选参数,表示当前项的索引位置:

 // 父作用域数据
 const parentMessage = ref('Parent')
 // 列表数据
 const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
 <!-- 使用索引和父作用域数据 -->
 <li v-for="(item, index) in items">
   {{ parentMessage }} - {{ index }} - {{ item.message }}
 </li>

输出结果

 Parent - 0 - Foo
 Parent - 1 - Bar

作用域说明

  • v-for 块内可以访问父作用域的属性(如示例中的 parentMessage
  • 迭代变量(itemindex)仅在当前 v-for 作用域内有效
  • 这与 JavaScript 中的 forEach 回调函数作用域类似

解构赋值

v-for 中可以使用对象解构,简化对嵌套数据的访问:

 <!-- 解构对象属性 -->
 <li v-for="{ message } in items">
   {{ message }}
 </li>
 
 <!-- 带索引的解构 -->
 <li v-for="({ message }, index) in items">
   {{ message }} {{ index }}
 </li>

多层嵌套 v-for

对于多层嵌套的列表,内层 v-for 可以访问外层作用域的数据:

 <li v-for="item in items">
   <span v-for="childItem in item.children">
     {{ item.message }} {{ childItem }}
   </span>
 </li>

迭代语法变体

除了 in 之外,还可以使用 of 作为分隔符,更接近 JavaScript 的迭代器语法:

 <div v-for="item of items"></div>

遍历对象

v-for 不仅可以遍历数组,还可以遍历对象的属性:

const myObject = reactive({
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10'
})
<!-- 遍历对象值 -->
<ul>
  <li v-for="value in myObject">
    {{ value }}
  </li>
</ul>

<!-- 包含属性名 -->
<li v-for="(value, key) in myObject">
  {{ key }}: {{ value }}
</li>

<!-- 包含索引 -->
<li v-for="(value, key, index) in myObject">
  {{ index }}. {{ key }}: {{ value }}
</li>

注意:对象遍历顺序基于 Object.values() 的返回顺序

范围值迭代

v-for 可以直接接受一个整数值,渲染从 1 到该数值的范围:

<!-- 渲染 1 到 10 的数字 -->
<span v-for="n in 10">{{ n }}</span>

注意:范围迭代从 1 开始,而非 0

template 上的 v-for

v-if 类似,可以在 <template> 标签上使用 v-for 渲染多个元素的块:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

这种方式不会额外创建包裹元素,适合需要渲染多个同级元素的场景。

v-for 与 v-if 共存问题

v-forv-if 同时存在于同一节点时,v-if 具有更高的优先级,这意味着 v-if 无法访问 v-for 的迭代变量。

不推荐的用法

<!-- 错误示例:v-if 无法访问 todo -->
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo.name }}
</li>

正确的用法

<!-- 正确:将 v-for 放在 template 上 -->
<template v-for="todo in todos">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>

最佳实践

  • 避免同时使用 v-ifv-for
  • 过滤列表:使用计算属性返回过滤后的数组
  • 条件渲染整个列表:将 v-if 移至列表容器元素

通过 key 管理状态

Vue 默认采用"就地更新"策略更新 v-for 渲染的列表,这意味着当数据顺序改变时,Vue 不会移动 DOM 元素,而是更新元素内容。

为了让 Vue 能够跟踪每个节点的标识,从而实现高效的重用和重排序,需要提供唯一的 key 属性:

<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

使用 <template v-for>key 应放在 <template> 上:

<template v-for="todo in todos" :key="todo.name">
  <li>{{ todo.name }}</li>
</template>

注意事项

  • key 必须绑定唯一的值(字符串或数字)
  • 不要使用对象作为 key
  • 推荐在大多数情况下使用 key,除非列表非常简单

组件上使用 v-for

可以在组件上直接使用 v-for,但需要显式传递数据作为 props:

<MyComponent
  v-for="(item, index) in items"
  :item="item"  <!-- 传递当前项数据 -->
  :index="index"  <!-- 传递索引 -->
  :key="item.id"  <!-- 提供唯一 key -->
/>

注意:Vue 不会自动将迭代数据注入组件,必须显式通过 props 传递,这使组件更加灵活和可重用。

数组变化侦测

Vue 能够侦听响应式数组的变更,并触发视图更新,主要通过两种方式:

1. 变更方法

Vue 对数组的以下变更方法进行了包装,调用这些方法会自动触发更新:

  • push():向数组末尾添加元素
  • pop():删除并返回数组最后一个元素
  • shift():删除并返回数组第一个元素
  • unshift():向数组开头添加元素
  • splice():添加/删除数组元素
  • sort():排序数组
  • reverse():反转数组

示例

const items = ref([1, 2, 3])
items.value.push(4)  // 会触发视图更新

2. 替换数组

对于不会修改原数组的方法(如 filter()concat()slice()),需要将返回的新数组赋值给原数组:

// 过滤数组并替换原数组
items.value = items.value.filter(item => item > 2)

优化说明:Vue 会智能重用已有的 DOM 元素,因此替换数组是高效的操作,不会完全重新渲染列表。

展示过滤或排序后的结果

当需要展示数组的过滤或排序版本而不修改原数组时,可以使用计算属性:

 const numbers = ref([1, 2, 3, 4, 5])
 
 // 计算属性返回偶数
 const evenNumbers = computed(() => {
   return numbers.value.filter(n => n % 2 === 0)
 })
 <!-- 使用计算属性 -->
 <li v-for="n in evenNumbers">{{ n }}</li>

复杂场景:在多层嵌套中,可以使用方法返回过滤后的结果:

 const sets = ref([
   [1, 2, 3, 4, 5],
   [6, 7, 8, 9, 10]
 ])
 
 // 过滤偶数的方法
 function even(numbers) {
   return numbers.filter(number => number % 2 === 0)
 }
 <ul v-for="numbers in sets">
   <li v-for="n in even(numbers)">{{ n }}</li>
 </ul>

注意:在计算属性中使用 reverse()sort() 时,应先创建数组副本,避免修改原数组:

 // 错误:会修改原数组
 return numbers.reverse()
 
 // 正确:创建副本后操作
 return [...numbers].reverse()



点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4