当前位置: 首页 > news >正文

Vue 列表渲染完全指南:v-for 核心用法、key 原理及数据监测实战(附代码案例)

          在 Vue 开发中,列表渲染是高频需求,v-for指令作为核心工具,能高效处理数组、对象等数据的展示。但很多开发者在使用时容易忽略key的正确用法、数据响应式更新等细节,导致页面性能问题或渲染异常。本文将从v-for基础用法入手,深入解析key的底层原理,结合数组方法、列表过滤排序案例,以及 Vue 数据监测机制,帮你彻底掌握 Vue 列表渲染的核心技巧。

一、v-for 指令:列表渲染的基础

v-for是 Vue 专门用于列表渲染的指令,支持遍历数组、对象、字符串及指定次数,核心是 “数据驱动视图”,即数据变化时自动更新页面。

1. 核心语法

v-for="(item, index) in 数据源" :key="唯一标识"
  • item:数据源中的每一项(数组元素、对象属性值等)。
  • index:可选,当前项的索引值。
  • :key:必填(高效渲染关键),用于标识虚拟 DOM 节点的唯一性。

2. 常见遍历场景

(1)遍历数组(最常用)

适用于展示列表数据,如人员列表、商品列表等。

<div id="root"><h2>人员列表</h2><ul><!-- p为数组中的每个对象,index为索引 --><li v-for="(p, index) in persons" :key="p.id">{{p.name}}--{{p.age}}--{{p.sex}}</li></ul>
</div><script>
new Vue({el: '#root',data: {persons: [{ id: '001', name: '张三', age: 18, sex: '男' },{ id: '002', name: '李四', age: 19, sex: '女' },{ id: '003', name: '王五', age: 20, sex: '男' }]}
})
</script>
(2)遍历对象

适用于展示详情类数据,如商品信息、用户资料等。

<h2>汽车信息</h2>
<ul><!-- value为属性值,k为属性名 --><li v-for="(value, k) of car" :key="k">{{k}}--{{value}}</li>
</ul><script>
data: {car: {name: '奥迪A7',price: '70万',color: '至尊灰'}
}
</script>
(3)遍历字符串(极少用)

遍历字符串的每个字符,实际开发中几乎不用。

<h2>遍历字符串</h2>
<ul><li v-for="(val, index) in str" :key="index">{{index}}--{{val}}</li>
</ul><script>
data: {str: 'hello' // 输出:0-h,1-e,2-l,3-l,4-o
}
</script>
(4)遍历指定次数(极少用)

按次数渲染元素,适用于固定数量的占位布局。

二、key 的底层原理:面试核心考点

key是虚拟 DOM 的唯一标识,直接影响 Vue 的渲染性能和正确性,是面试高频问题,需深入理解其作用机制。

1. 前置知识:真实 DOM vs 虚拟 DOM

(1)真实 DOM 的问题

浏览器解析 HTML 会生成真实 DOM 树,每次操作真实 DOM(如更新内容),都会触发 “DOM 树重构→样式计算→布局→绘制” 的完整流程,频繁操作会导致页面卡顿。

(2)虚拟 DOM 的优势

虚拟 DOM 是 Vue 创建的 JS 对象,用于模拟真实 DOM 结构。数据变化时,Vue 先更新虚拟 DOM,再通过 “diff 算法” 对比新旧虚拟 DOM 的差异,仅将变化部分同步到真实 DOM,减少无效操作,提升性能。

(3)代码对比:真实 DOM vs 虚拟 DOM 性能

<div id="app"></div>
<script>
// 真实DOM操作:10000次更新,每次都操作真实DOM
let box = document.querySelector('#app');
console.time('真实DOM');
for (let i = 0; i <= 10000; i++) {box.innerHTML = i;
}
console.timeEnd('真实DOM'); // 耗时较长// 虚拟DOM思路:先操作JS变量,最后一次更新真实DOM
let num = 0;
console.time('虚拟DOM思路');
for (let i = 0; i <= 10000; i++) {num = i;
}
box.innerHTML = num;
console.timeEnd('虚拟DOM思路'); // 耗时极短
</script>

2. key 的核心作用

key 作为虚拟 DOM 节点的唯一标识,是 diff 算法对比新旧虚拟 DOM 的 “依据”,对比规则如下:

  • 旧虚拟 DOM 中找到与新虚拟 DOM 相同的 key:
    • 若虚拟 DOM 内容未变,直接复用之前的真实 DOM(性能优化)。
    • 若内容改变,生成新的真实 DOM 替换旧节点。
  • 旧虚拟 DOM 中未找到相同的 key:创建新的真实 DOM 并渲染。

3. 用 index 作为 key 的隐患

很多开发者习惯用index作为 key,但在数据发生 “逆序添加、逆序删除” 等破坏顺序的操作时,会出现问题:

(1)问题 1:无效 DOM 更新,性能浪费

假设数组逆序添加元素,index会重新分配,导致 Vue 误判 “节点已变更”,触发不必要的真实 DOM 更新。

(2)问题 2:输入类 DOM 渲染异常

若列表包含输入框,index变化会导致输入框的值与数据不匹配。

<div id="root"><button @click="add">添加老刘</button><ul><li v-for="(p, index) in persons" :key="index">{{p.name}}--{{p.age}}<input type="text"> <!-- 输入内容会错乱 --></li></ul>
</div>
<script>
new Vue({el: '#root',data: {persons: [{ id: '001', name: '张三', age: 18 },{ id: '002', name: '李四', age: 19 }]},methods: {add() {this.persons.unshift({ id: '003', name: '老刘', age: 40 }); // 逆序添加}}
})
</script>

4. 正确用法:用唯一标识作为 key

应使用数据的唯一标识(如id、手机号、身份证号)作为 key,确保节点标识的稳定性,避免上述问题。

<li v-for="(p, index) in persons" :key="p.id"> <!-- 用id作为key -->{{p.name}}--{{p.age}}<input type="text">
</li>

5. 结论

  • 优先使用数据的唯一标识作为 key(如id)。
  • 若仅用于静态展示,无数据顺序变更,用index作为 key 也可。

三、数组常用方法:列表数据的增删改查

Vue 对数组的 7 个方法进行了 “包装”,调用这些方法时会自动触发视图更新(响应式),其他方法(如indexOffilter)需配合响应式 API 使用。

1. 响应式数组方法(直接触发视图更新)

  • 增:push()(尾部添加)、unshift()(头部添加)。
  • 删:pop()(尾部删除)、shift()(头部删除)、splice(index, count)(指定位置删除 / 替换)。
  • 改:sort()(排序)、reverse()(反转)。

2. 非响应式数组方法(需配合其他操作)

(1)filter ():数组过滤

返回满足条件的新数组,不改变原数组,常用于列表筛选。

const arr = [1, 6, 9, 3, 7, 5];
const newArr = arr.filter(item => item >= 5); 
console.log(newArr); // [6, 9, 7, 5]
(2)indexOf ():查找元素索引

返回元素在数组 / 字符串中第一次出现的索引,不存在返回-1,常用于判断元素是否存在。

javascript

运行

const arr = ['马冬梅', '周杰伦', '张三'];
console.log(arr.indexOf('马冬梅')); // 0(存在)
console.log(arr.indexOf('李四')); // -1(不存在)
(3)sort ():数组排序

默认按字符串排序,需自定义 comparator 实现数字排序。

// 数字数组排序
const arr = [3, 123, 35, 4];
// 升序:a - b
arr.sort((a, b) => a - b); // [3, 4, 35, 123]
// 降序:b - a
arr.sort((a, b) => b - a); // [123, 35, 4, 3]// 对象数组排序(按id升序)
const arr1 = [{ id: 2 }, { id: 13 }, { id: 6 }];
arr1.sort((a, b) => a.id - b.id);

四、实战案例:列表过滤与排序

结合v-for、计算属性、数组方法,实现带筛选和排序功能的列表,体现 “数据驱动视图” 的核心思想。

1. 列表过滤(按关键词搜索)

通过v-model绑定搜索关键词,用filter()过滤数据,支持实时筛选。

<div id="root"><h2>人员列表</h2><input type="text" placeholder="输入名字搜索" v-model="keyWord"><ul><li v-for="(p, index) in filPersons" :key="p.id">{{p.name}}--{{p.age}}--{{p.sex}}</li></ul>
</div><script>
new Vue({el: '#root',data: {keyWord: '',persons: [{ id: '001', name: '马冬梅', age: 18, sex: '女' },{ id: '002', name: '周杰伦', age: 20, sex: '男' },{ id: '003', name: '马东雨', age: 19, sex: '女' }]},computed: {// 计算属性:实时返回过滤后的数组filPersons() {return this.persons.filter(p => {// 包含关键词则保留(不区分大小写可加toLowerCase())return p.name.indexOf(this.keyWord) !== -1;});}}
})
</script>

2. 列表排序(升序 / 降序 / 原序)

在过滤基础上添加排序功能,通过按钮切换排序类型。

<div id="root"><h2>人员列表</h2><input type="text" placeholder="输入名字搜索" v-model="keyWord"><button @click="sortType=2">年龄升序</button><button @click="sortType=1">年龄降序</button><button @click="sortType=0">恢复原序</button><ul><li v-for="(p, index) in filPersons" :key="p.id">{{p.name}}--{{p.age}}--{{p.sex}}</li></ul>
</div><script>
new Vue({el: '#root',data: {keyWord: '',sortType: 0, // 0-原序,1-降序,2-升序persons: [{ id: '001', name: '马冬梅', age: 30, sex: '女' },{ id: '002', name: '周杰伦', age: 18, sex: '男' },{ id: '003', name: '马东雨', age: 33, sex: '女' }]},computed: {filPersons() {// 先过滤const arr = this.persons.filter(p => {return p.name.indexOf(this.keyWord) !== -1;});// 再排序if (this.sortType !== 0) {arr.sort((a, b) => {return this.sortType === 2 ? a.age - b.age : b.age - a.age;});}return arr;}}
})
</script>

五、Vue 数据监测:确保列表响应式更新

Vue 能监测data中数据的变化并触发视图更新,但对对象、数组的监测有特殊规则,若操作不当会导致 “数据变了,视图不变”。

1. 数据监测原理

(1)监测对象数据

Vue 通过 “数据劫持”(Object.defineProperty)给对象的属性添加settergetter,属性变化时触发setter,进而更新视图。注意:新添加的对象属性默认不具备响应式,需用Vue.set()vm.$set()手动处理。

(2)监测数组数据

Vue 没有劫持数组的索引,而是通过包装数组方法(如pushsplice),调用方法时触发视图更新。注意:直接修改数组索引(如this.arr[0] = 10)不会触发视图更新。

2. 响应式更新的正确操作

(1)对象数据:添加响应式属性
// 给student对象添加sex属性(响应式)
Vue.set(this.student, 'sex', '男');
// 或
this.$set(this.student, 'sex', '男');
(2)数组数据:修改元素的正确方式
// 方式1:使用包装方法
this.student.hobby.push('看电影'); // 新增
this.student.hobby.splice(0, 1, '打篮球'); // 替换
this.student.hobby.sort(); // 排序// 方式2:使用Vue.set()
Vue.set(this.student.hobby, 0, '打篮球');

3. 常见问题:数据变了,视图不变

// 错误:直接修改数组索引,非响应式
this.persons[0] = { id: '001', name: '马老师', age: 50 };// 正确:用splice替换
this.persons.splice(0, 1, { id: '001', name: '马老师', age: 50 });// 错误:给对象新增属性,非响应式
this.student.sex = '男';// 正确:用Vue.set()
Vue.set(this.student, 'sex', '男');

4. 数据监测总结

  • Vue 监测data中所有层次的数据。
  • 对象:新增属性需用Vue.set(),否则非响应式。
  • 数组:修改元素需用包装方法或Vue.set(),直接修改索引无效。
  • Vue.set()不能给vmvm的根数据对象添加属性。

六、总结

Vue 列表渲染的核心是v-for指令,配合key优化渲染性能,结合数组方法和计算属性实现复杂功能,同时需遵循 Vue 数据监测规则确保响应式更新。关键要点:

  1. v-for支持数组、对象等数据源,key需用唯一标识。
  2. 虚拟 DOM 通过key对比差异,提升渲染效率。
  3. 数组响应式修改依赖包装方法,对象新增属性需用Vue.set()
  4. 列表过滤排序优先用计算属性,实现数据与视图的联动。

掌握这些知识点,能轻松应对 Vue 列表渲染的各类场景,避免常见坑点,提升开发效率和页面性能。

http://www.dtcms.com/a/600549.html

相关文章:

  • webrtc降噪-PriorSignalModelEstimator类源码分析与算法原理
  • 如何在电商上购物网站企业咨询管理是干嘛的
  • 重庆大型的网站建设企业社交网站定制
  • 门户网站设计运城市网站建设公司
  • 网站 公司备案与个人备案如何用群晖做自己的网站
  • 商务网站建设实训报告1500字炫酷文字制作网站
  • 给你一个网站你怎么做的网站建设的风格
  • 手机网站和微信网站有哪些opensearch wordpress
  • 餐饮公司网站建设的特点中山网站建设的公司
  • 青岛网站设计多少钱苏州工业园区两学一做教育网站
  • 做网站的备案外包服务公司排名
  • 做网站淮南请人开发一个app要多少钱
  • 个人做论坛网站需要哪些备案.net 企业网站源码
  • 广州手机网站定制信息一个app软件
  • 做网站莱芜短视频推广引流方案
  • 建一个商城网站需要多久小程序游戏排行榜2023
  • 购物网站单页模板新媒体如何运营推广
  • 小说盗版网站怎么做郑州seo招聘
  • 网站建设规划模板内江如何做百度的网站
  • 旅游网站开发说明青岛即墨网站网页设计
  • 网站服务器买了后怎么做汕头服饰网站建设
  • 有什么好的提供外链网站lnmp wordpress建设多网站
  • 什么摄像头做直播网站seo技巧与技术
  • 做网站标题居中代码大学生创业项目
  • 网站制作公司哪儿济南兴田德润有活动吗保定企业建站程序
  • 简单响应式网站设计代码龙岗网站维护
  • 北京快速网站建设商城首页网站
  • 内贸网站有多少宣传产品网站
  • 设计网站 f德州网页设计师培训
  • 2018爱情动做网站网站搜索栏怎么做