vue之v-for的各种使用

本文深入探讨Vue.js中v-for指令的高级用法,包括使用数组和对象渲染列表、维护状态、数组更新检测、对象变更检测、显示过滤排序结果等。通过实例,读者将学会如何高效地操作数据,理解Vue的虚拟DOM算法,掌握关键的编程技巧。

用 v-for 把一个数组对应为一组元素

我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
在 v-for 块中,我们可以访问所有父作用域的属性。v-for 还支持一个可选的第二个参数,即当前项的索引。
html:


<ul id="a">
  <li v-for="(item, index) in items">
    {{ msg1 }} - {{ index }} - {{ item.msg }}
  </li>
</ul>


js:


var aa = new Vue({
  el: '#a',
  data: {
   msg1: '信息',
    items: [
      { msg: '明月几时有' },
      { msg: '把酒问青天' }
    ]
  }
})

结果:
在这里插入图片描述
注意:也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法

在 v-for 里使用对象

可以用 v-for 来遍历一个对象的属性。
html:


	<ul id="o" class="demo">
  <li v-for="v in object">
    {{ v }}
  </li>
</ul>

js:


new Vue({
		  el: '#o',
		  data: {
		    object: {
		      title: '全职高手',
		      author: '蝴蝶兰',
		      time: '2012-4-2'
		    }
		  }
		})	

结果:
在这里插入图片描述
也可以用三个参数:
一个值,一个 property 名称 (也就是键名),一个索引

<ul id="o" class="demo">
  <li v-for="(v,name,index) in object">
   {{index}} - {{ name }} - {{v}}
  </li>
</ul>

在这里插入图片描述
注意:在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。

维护状态

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性:

<li v-for="(item, index) of items" :key="item.id">
    {{ msg1 }} : {{ index }} : {{ item.msg }}
  </li>

尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

因为它是 Vue 识别节点的一个通用机制,key 与 v-for 特别关联。

key的其他用途:
	key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,
	在新旧 nodes 对比时辨识用相同类型元素的算法。
	使用 key,它会基于 key 的变化重新排列元素顺序,
	并且会移除 key 不存在的元素。
	它也可以用于强制替换元素/组件而不是重复使用它。
	有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
	
	当你遇到如下场景时它可能会很有用:
	①完整地触发组件的生命周期钩子
	②触发过渡
	<transition>
    <span :key="text">{{ text }}</span>
     </transition>
     当 text 发生改变时,<span> 会随时被更新,因此会触发过渡。

注意:不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

数组更新检测

变异方法 (mutation method)

Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

push() 接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度

pop() 从数组末尾移除最后一项,减少数组的length值,然后返回移除的项

shift() 移除数组中的第一个项并返回该项,同时数组的长度减1

unshift() 在数组前端添加任意个项并返回新数组长度

splice() 删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员

sort() 调用每个数组项的toString()方法,然后比较得到的字符串排序,返回经过排序之后的数组

reverse() 用于反转数组的顺序,返回经过排序之后的数组

你可以打开控制台,然后对前面例子的 items 数组尝试调用变异方法。比如 aa.items.push({ msg: ‘水调歌头’ })。

替换数组

非变异 (non-mutating method) 方法,例如 filter()、concat() 和 slice() 。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:

  concat() 连接两个或更多的数组,并返回结果。
  slice()	选取数组的的一部分,并返回一个新数组。  不包括最后一位
filter()	过滤数组方法
aa.items = aa.items.filter(function (item) {
  return item.msg.match(/明月几时有/)
})

Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

注意事项

由于 JavaScript 的限制,Vue 不能检测以下数组的变动:

1,当你利用索引直接设置一个数组项时
2,当你修改数组的长度时

对象变更检测注意事项

还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除
对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。
可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性
你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名
有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。

显示过滤/排序后的结果

显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据。
使用filter()

在 v-for 里使用值范围

v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

在 上使用 v-for

类似于 v-if,你也可以利用带有 v-for 的 来循环渲染一段包含多个元素的内容。

v-for 与 v-if 一同使用

注意:不推荐在同一元素上使用 v-if 和 v-for

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用

而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 )上。

在组件上使用 v-for

任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 prop

不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

案例:
html:

<div id="example">
  <form v-on:submit.prevent="add">
    <label for="new-todo">添加信息</label>
    <input
      v-model="context"
      id="new-todo"
      placeholder="输入添加内容"
    >
    <button>新增</button>
  </form>
  <ul>
    <li
      is="list"
      v-for="(example, index) in todos"
      v-bind:key="example.id"
      v-bind:title="example.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
	
  </ul>
</div>

js:

Vue.component('list',{
			template:'<li>{{title}}<button @click="$emit(\'remove\')">删除</button></li>',
			props:['title']
		})
		
		
		new Vue({
			el:'#example',
			data:{
				 context:'',
				 todos: [
      {
        id: 1,
        title: '吃饭',
      },
      {
        id: 2,
        title: '睡觉',
      },
      {
        id: 3,
        title: '打豆豆'
      }
    ],
	nextId:4
			},
			methods: {
    add() {
      this.todos.push({
        id: this.nextId++,
        title: this.context
      })
      this.context= ''
    }
  }
		})

结果:
在这里插入图片描述
注意这里的 is=list" 属性。这种做法在使用 DOM 模板时是十分必要的,因为在

  • 元素内只有
  • 元素会被看作有效内容。这样做实现的效果与 相同,但是可以避开一些潜在的浏览器解析错误。

如果需要更详细的的讲解,可以登录有关网站了解
https://cn.vuejs.org/v2/guide/list.html

以下是一些Vue中v-for使用实例: ### 循环简单数组 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-for简单数组示例</title> </head> <body> <div id="app"> <!-- 仅获取每一项 --> <p v-for="item in list">{{item}}</p> <!-- 获取每一项和索引值 --> <p v-for="(item, i) in list">索引值:{{i}}---每一项:{{item}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { list: ['apple', 'banana', 'cherry'] } }); </script> </body> </html> ``` ### 循环复杂数组 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-for复杂数组示例</title> </head> <body> <div id="app"> <p v-for="(item, i) in list1">索引值:{{i}}--id:{{item.userid}}---姓名:{{item.username}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { list1: [ { userid: 1, username: '张三' }, { userid: 2, username: '李四' }, { userid: 3, username: '王五' } ] } }); </script> </body> </html> ``` ### 循环对象 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-for循环对象示例</title> </head> <body> <div id="app"> <p v-for="(val, key, i) in list2">id:{{val}}, name:{{key}}, index:{{i}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { list2: { '张三': 1, '李四': 2, '王五': 3 } } }); </script> </body> </html> ``` ### 循环迭代数字 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-for循环迭代数字示例</title> </head> <body> <div id="app"> <p v-for="count in 10">这是第{{count}}次循环</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> new Vue({ el: '#app' }); </script> </body> </html> ``` ### 组件中使用v-for ```html <template> <div> <my-component v-for="(item, index) in list" :key="index" :item="item"></my-component> </div> </template> <script> import MyComponent from './MyComponent.vue' export default { components: { MyComponent }, data() { return { list: [ { name: '张三', age: 18 }, { name: '李四', age: 20 }, { name: '王五', age: 22 } ] } } } </script> ``` ### 动态添加元素并更新视图 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-for动态添加元素示例</title> </head> <body> <div id="demo"> <p v-for="item in items" :key="item">{{item}}</p> <button @click="addItem">添加元素</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> const app = new Vue({ el: '#demo', data: { items: ['a', 'b', 'c', 'd', 'e'] }, methods: { addItem() { this.items.push('f'); } } }); </script> </body> </html> ``` ### 动态删除元素并更新视图 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-for动态删除元素示例</title> </head> <body> <ul> <li v-for="(item, index) in booksList" :key="item.id"> <span>{{ item.name }}</span> <span>{{ item.author }}</span> <button @click="del(item.id)">删除</button> </li> </ul> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> new Vue({ el: 'ul', data: { booksList: [ { id: 1, name: '书1', author: '作者1' }, { id: 2, name: '书2', author: '作者2' }, { id: 3, name: '书3', author: '作者3' } ] }, methods: { del(id) { this.booksList = this.booksList.filter(item => item.id!== id); } } }); </script> </body> </html> ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值