列表渲染
在html中如果我们想要循环渲染一段内容该怎么办
使用js+for循环,然后生成一个模板,再插入到html中
但是在vue我们有一个更好的语法糖,就是v-for
v-for
首先在data声明一个items的数组数据
Vue.createApp({
data() {
return {
items: [{ message: 'Foo' }, { message: 'Bar' }]
}
}
}).mount('#array-rendering')
在模板中可以直接
"item in items"
这个时候item就是items数组中的每一个对象
<ul id="array-rendering">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
我们还有其他参数,比如可以使用v-for="(item,index) in items"
item,index是可以随便名字的,第一个是对象,第二个则是当前的索引顺序
Vue的数据是
Vue.createApp({
data() {
return {
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }]
}
}
}).mount('#array-with-index')
而模板则可以
<ul id="array-with-index">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
我们也可以使用of代替in来作为分隔符,它更接近js迭代器的语法,但是这里我个人是不太推荐这种写法的
因为个人喜好
在v-for使用对象
除了遍历数组,我们也可以直接遍历对象,会直接获取属性的内容
Vue为
Vue.createApp({
data() {
return {
myObject: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
}
}).mount('#v-for-object')
此时模板为
<ul id="v-for-object" class="demo">
<li v-for="value in myObject">
{{ value }}
</li>
</ul>
也可以使用()写法,这时第二项是属性名,第三项为index
<li v-for="(value, name, index) in myObject">
{{ index }}. {{ name }}: {{ value }}
</li>
注意
遍历的时候使用object.keys函数的结果进行遍历,不保证在不同引擎下的结果和顺序一致
维护状态
在v-for的情况下,我们通常会就地更新,通常如果想要更高效的运行,需要对每个节点标识一个身份
设置一个的key,目前推荐对每一个v-for都强制设置key
如
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
key只能使用字符串和数值类型
数组更新检测
Vue对数组的更新方法进行了封装,如果调用了对应的函数,将会触发视图的重新更新,修改的方法为
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
替换数组
当调用一些不改变原始数组,返回一个新数组的函数,如fileter,concat,slice等函数
我们直接使用新数组替换旧输入
如
example1.items = example1.items.filter(item => item.message.match(/Foo/))
这个时候因为key值和内容值的显示值相等,这个时候重新渲染的损耗依然是非常低的
显示排序后的结果
我们可以不变更原始数据,而使用计算属性,返回一个处理后的数据,然后进行渲染
data() {
return {
numbers: [ 1, 2, 3, 4, 5 ]
}
},
computed: {
evenNumbers() {
return this.numbers.filter(number => number % 2 === 0)
}
}
<li v-for="n in evenNumbers" :key="n">{{ n }}</li>
在计算属性不适用的情况下,我们也可以直接使用函数
但是能使用计算属性的情况下,不要使用函数
因为计算属性存在缓存,相比函数损耗更大
data() {
return {
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
}
},
methods: {
even(numbers) {
return numbers.filter(number => number % 2 === 0)
}
}
<ul v-for="numbers in sets">
<li v-for="n in even(numbers)" :key="n">{{ n }}</li>
</ul>
在v-for使用整数
我们在v-for也可以使用整数,这时候模板将会重复对应个数
<div id="range" class="demo">
<span v-for="n in 10" :key="n">{{ n }} </span>
</div>
在template使用v-for
我们可以在外包裹一层template
这个时候template相当于一个虚拟的元素,仅是在逻辑上的元素,实际渲染的时候不会显示
相比使用div等进行渲染,少渲染了元素,同时在ul内,应使用li渲染,使用template进行循环渲染
更符合html语义和结构
<ul>
<template v-for="item in items" :key="item.msg">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-for和v-if组合使用
v-if的优先级更高,同时v-if没用权限访问v-for的变量,还有就是不推荐将二者组合使用
下列例子无法正常运行
<!-- 这将抛出一个错误,因为“todo” property 没有在实例上定义 -->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
可以将v-for移动到template标签来进行修正
<template v-for="todo in todos" :key="todo.name">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
在组件使用v-for
我们可以在组件上使用v-for,同时绑定对应的数据
这里使用了v-for和ket
而item和index是传入组件的数据,组件将使用props属性进行接受
<my-component
v-for="(item, index) in items"
:item="item"
:index="index"
:key="item.id"
></my-component>