浅谈vue.js中v-for循环渲染
发布时间 - 2026-01-11 02:31:30 点击率:次这两天学习了Vue.js 感觉v-for循环渲染这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记。

一、简介
vue.js 的循环渲染是依赖于 v-for 指令,它能够根据 vue 的实例里面的信息,循环遍历所需数据,然后渲染出相应的内容。它可以遍历数组类型以及对象类型的数据,js 里面的数组本身实质上也是对象,这里遍历数组和对象的时候,方式相似但又稍有不同。
(一)遍历对象
<div id="app">
<ul>
<li v-for="(val, key, index) in me">{{index}}. {{key}}: {{val}}</li>
</ul>
</div>
...
var vm = new Vue({
el: '#app',
data: {
me: {
name: 'Dale',
age: 22,
sex: 'male',
height: 170
}
}
});
这里,v-for 接收的参数相对较复杂,但是可以分为三个部分:
(1)括号及其内的遍历结果信息(val, key, index)
其中,val 是遍历得到的属性值,key 是遍历得到的属性名,index 是遍历次序,这里的 key/index 都是可选参数,如果不需要,这个指令其实可以写成 v-for="val in me";
(2)遍历关键词 in
in 可以使用 of 替代,官方的说法是“它是最接近 JavaScript 迭代器的语法”,但其实使用上并没有任何区别;
(3)被遍历对象 me
me 是绑定在实例 data属性上的一个属性,实际上,它是有一个执行环境的,也即是我们接触最多的 vue 实例,模板中,我们仍旧可以像在 methods 以及计算属性中一样,通过 this 访问到它,这里的 me 其实就相当于 this.me,模板中直接写 this.me 也是可行的。
渲染结果如下:
<div id="app">
<ul>
<li>0. name: Dale</li>
<li>1. age: 22</li>
<li>2. sex: male</li>
<li>3. height: 170</li>
</ul>
</div>
(二)遍历数组
<div id="app">
<ul>
<li v-for="(item, index) in items">{{index}}. {{item}}</li>
</ul>
</div>
...
var vm = new Vue({
el: '#app',
data: {
items: ['apple', 'tomato', 'banana', 'watermelon']
}
});
和遍历对象相类似,最大的不同点在于对象的 “key” 和 “index” 是一致的,所以这里我们只需要取一个 index 即可,上面代码的渲染结果如下:
<div id="app">
<ul>
<li>0. apple</li>
<li>1. tomato</li>
<li>2. banana</li>
<li>3. watermelon</li>
</ul>
</div>
(三)遍历“整数”
理论上来说,整数并不是一个可遍历的单元,但是 vue 这里相当于给我们提供了一个方便方式来减少重复代码。
<div id="app">
<ul>
<li v-for="n in num">{{n}}</li>
</ul>
</div>
...
var vm = new Vue({
el: '#app',
data: {
num: 3
}
});
渲染结果如下:
<div id="app">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
二、实际应用
(一)对象、数组 & 组件
实际应用过程中,我们单独使用数组或者对象去描述我们的数据的情况很少,更常见的模式是结合了数组和对象两部分内容:
<div id="app">
<ul class="persons">
<li v-for="person in persons">name: {{person.name}}, age: {{person.age}};</li>
</ul>
</div>
...
var vm = new Vue({
el: '#app',
data: {
persons: [
{
name: 'Dale',
age: 22
},
{
name: 'Tim',
age: 30
},
{
name: 'Rex',
age: 23
}
]
}
});
本质上是遍历的一个数组,但是数组的每个元素却是一个对象,也就是上面的 person,我们可以通过 [] 以及 . 两种方式去访问这个对象的属性,比如这里的 name / age,渲染结果如下:
<div id="app">
<ul class="persons">
<li>name: Dale, age: 22;</li>
<li>name: Tim, age: 30;</li>
<li>name: Rex, age: 23;</li>
</ul>
</div>
实际上,更加常用且强大的模式,是使用组件与数组/对象进行组合,操作方式与上面相类似。
(二)与 v-if 组合
添加了 v-for 指令的标签,实际上也可以同时添加 v-if 指令,但值得注意的是,v-for 的优先级更高,渲染模板时,相当于对每次遍历的结果进行了一次条件判断。
<div id="app">
<ul class="persons">
<li v-for="person in persons" v-if="person.age >= 23">name: {{person.name}}, age: {{person.age}};</li>
</ul>
</div>
...
var vm = new Vue({
el: '#app',
data: {
persons: [
{
name: 'Dale',
age: 22
},
{
name: 'Tim',
age: 30
},
{
name: 'Rex',
age: 23
}
]
}
});
这里先遍历了 persons 的所有元素,然后检查每次得到的 person 的是否大于或等于 23,是则输出,否则不输出,渲染结果如下:
<div id="app">
<ul class="persons">
<li>name: Tim, age: 30;</li>
<li>name: Rex, age: 23;</li>
</ul>
</div>
如果要让 v-if 指令的优先级更高,可以考虑在 v-for 指令所绑定的标签的父级上添加 v-if 指令。
三、注意事项
(一)key
与 v-for 一样,在不绑定 key 属性的情况下,vue 默认会重用元素以提高性能,如果不需要它的默认行为,显式绑定一个唯一的 key 即可。
(二)数据 -> 视图更新
vue 的视图更新是依赖于 getter/setter 的,如果直接修改、增加、删除数组元素,并不会触发视图的更新。这里 vue 重写了如下方法:
- push
- pop
- shift
- unshift
- splice
- sort
- reverse
当通过它们修改数据的时候,将会触发视图的更新。
new Vue({
data: {
arr: [1, 2, 3]
}
});
比如上面这种情况,如果我们想要在执行 arr 的 push 等方法,因为 push 是数组类型数据从 Array.prototype.push 继承过来的,所以我们一般情况下有两种实现方式。
(1)修改 Array.prototype
Array.prototype.push = function () {
console.log(1);
}
([]).push(); // 1
这里我们修改了 Array.prototype 上的 push 方法,但是实际上,整个 prototype 属性都可以被重写,如 Array.prototype = xxx,这样做的好处很明显,在这一处进行修改,之后所有的数组类型都可以直接使用这个重写后的方法,实现和使用都非常简单;但是这样带来的副作用也特别明显,容易影响到其它的代码,其它使用这段代码的地方,除了功能实现上可能受到影响外,效率上也会有较大影响,原生 js 的代码都是经过特殊优化的,我们重写实现,效率肯定会受到影响,最重要的是,如果大家的代码在同一个环境下运行,然后都尝试重写同一个方法的话,最终结果不言而喻。
(2)增加自有方法
var arr = [];
arr.push = function () {
console.log(1);
}
arr.push(); // 1
Array.prototype.push.toString(); // "function push() { [native code] }"
这里修改了 arr 的 push 方法, 但是并不涉及 Array.prototype.push,因为读写一个对象的属性/方法的时候,js 总是先尝试访问 “ownproperty”,也就是 “hasOwnProperty” 所检测的内容,这里我们姑且将其称为“自有属性(方法)”。读取数据的时候,如果没有读取到内容,那么 js 会尝试向上搜索 __proto__ 上的数据;写数据的时候,如果有这个自有属性,则会将其覆盖,如果没有,则将其作为自有属性添加到改对象上,而不会尝试将其添加到 __proto__ 上,这样的规则,也是为了防止“子类”以外修改“父类”的属性、方法等。这种实现方式虽然可以避免上面修改 Array.prototype 的一系列缺点,但是它的问题就更加明显,因为每次创建这样一个“数组”,就要重新实现/绑定这样一系列方法,它所带来的开发效率、性能问题不容小觑。
(3)vue 的实现方式
var arr = [];
new Vue({
data: {
arr: arr
}
});
arr.push.toString(); // "function mutator() {var arguments$1 = arguments;... 这是 vue 自己的实现
Array.prototype.push.toString(); // "function push() { [native code] }"... 这是浏览器原生的实现
arr.hasOwnProperty('push'); // false 说明不是自有属性
以上说明 vue 既不是修改了 Array.prototype.push,又不是修改了自有属性。但我们通过 instanceof 操作符检查的时候,arr 又是 Array 的一个实例,那么它到底是怎么弄的实现的呢?或者说 vue 的 push 藏在哪儿呢?
var base = [];
var arr = [];
base.push = function () {
console.log(1);
};
arr.__proto__ = base;
arr.push(); // 1
arr.__proto__.push(); // 1
arr.__proto__.push.toString(); // "function push() { [native code] }"
实际上,vue 是利用了类似上面的方式,先创建了一个 Array 的实例,也就是一个数组类型的基础对象 base,然后为它添加了一个自有方法 push,最后用 base 覆盖了需要扩展的 arr 对象的 __proto__ 属性。
这里需要重写 push 等方法的数组,我们只需要将其 __proto__ 指向 base 数组,在读新创建的数组的 push 的时候,发现它并没有这样一个自有方法,那么它就尝试读 __proto__ 上的方法,发现 __proto__ 属性(也即 base 数组)上有这样一个自有方法,那么它就不必再向上搜索而直接使用 base.push。
通过这种方式,我们不必为每一个数组重写一遍 push 方法,也不必去修改 Array.prototype ,看起来倒像是一个两全其美的方法。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# vue.js
# 循环渲染
# v
# for
# 渲染
# vue中 v-for循环的用法详解
# Vue.js常用指令汇总(v-if、v-for等)
# vue.js指令v-for使用及索引获取
# 使用vue中的v-for遍历二维数组的方法
# VUE中v-model和v-for指令详解
# Vue中v-for的9种使用案例总结大全
# 遍历
# 关键词
# 重写
# 将其
# 绑定
# 这样一个
# 都是
# 这是
# 不需要
# 它是
# 更高
# 如果没有
# 只需要
# 上也
# 它就
# 实际应用
# 自己的
# 的是
# 是一个
# 也不
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
Python文件异常处理策略_健壮性说明【指导】
Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
LinuxCD持续部署教程_自动发布与回滚机制
深圳网站制作的公司有哪些,dido官方网站?
Laravel如何使用Collections进行数据处理?(实用方法示例)
高防服务器租用如何选择配置与防御等级?
js实现获取鼠标当前的位置
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程
Android Socket接口实现即时通讯实例代码
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
如何在IIS中新建站点并配置端口与IP地址?
焦点电影公司作品,电影焦点结局是什么?
JavaScript如何实现继承_有哪些常用方法
如何在 Pandas 中基于一列条件计算另一列的分组均值
Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程
Laravel如何实现文件上传和存储?(本地与S3配置)
Laravel如何记录自定义日志?(Log频道配置)
Python企业级消息系统教程_KafkaRabbitMQ高并发应用
Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
奇安信“盘古石”团队突破 iOS 26.1 提权
魔方云NAT建站如何实现端口转发?
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何用JavaScript实现文本编辑器_光标和选区怎么处理
中山网站制作网页,中山新生登记系统登记流程?
如何快速搭建高效香港服务器网站?
利用JavaScript实现拖拽改变元素大小
使用spring连接及操作mongodb3.0实例
夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
如何快速搭建二级域名独立网站?
黑客入侵网站服务器的常见手法有哪些?
如何自定义建站之星模板颜色并下载新样式?
网站建设整体流程解析,建站其实很容易!
Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控
如何在腾讯云服务器快速搭建个人网站?
JavaScript如何实现路由_前端路由原理是什么
Laravel如何保护应用免受CSRF攻击?(原理和示例)
EditPlus 正则表达式 实战(3)
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
什么是javascript作用域_全局和局部作用域有什么区别?
Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置
清除minerd进程的简单方法
大连 网站制作,大连天途有线官网?
Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
上一篇:宜兴网站建设如何选择专业服务商?
上一篇:宜兴网站建设如何选择专业服务商?

