vue列表渲染、key作用与原理、列表过滤排序
一、列表渲染
v-for指令:用于遍历数据
语法:
v-for="(item, index) in xxx" :key="yyy"
// 可以用of替代in作为分隔符
v-for="item of items"
示例:其中items是源数据数组,item是被迭代的数组元素的别名
<ul>
<li v-for="(item,index) in items" :key="item.id">
{{item.message}}
</li>
</ul>
var vm = new Vue({
el: '#app',
data: {
items:
{ id:1, message: 'Foo' },
{ id:2, message: 'Bar' }
]
}
})
可遍历数组、对象、字符串(用的少)、指定次数(用的少)
1、遍历数组
<ul>
<li v-for="(item,index) in items" :key="item.id">
{{item.message}}
</li>
</ul>
var vm = new Vue({
el: '#app',
data: {
items: [
{ id:1, message: 'Foo' },
{ id:2, message: 'Bar' }
]
}
})
2、遍历对象,在遍历对象时,会按Object.keys()的结果遍历,但不能保证它的结果在不同的JavaScript引擎下都一致。
<ul>
<li v-for="(val,key,index) in person" :key="key">
{{val}}--{{key}}--{{index}}
</li>
</ul>
var vm = new Vue({
el:"#app",
data:{
person:{
id:1,
name:"张三",
age:20
}
}
})
// 输出结果如下:
1--id--0
张三--name--1
20--age--2
3、遍历字符串(用得少)
<ul>
<li v-for="(chart,index) in str" :key="index">
{{chart}}--{{index}}
</li>
</ul>
var vm = new Vue({
el:"#app",
data:{
str:"hello"
}
})
// 输出结果如下:
h--0
e--1
l--2
l--3
o--4
4、遍历指定次数(用得少)
<ul>
<li v-for="(number,index) in 5" :key="index">
{{number}}--{{index}}
</li>
</ul>
var vm = new Vue({
el:"#app",
data:{}
})
// 输出结果如下:
1--0
2--1
3--2
4--3
5--4
二、key作用与原理
给节点做个标识,相当于人类的身份证号
1、虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较
2、对比规则:
旧虚拟DOM中找到了与新虚拟DOM相同的key:
若虚拟DOM中内容没有变化,直接使用之前的真实DOM
若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到页面
3、用index作为key可能会引起的问题:
若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新=》界面效果没问题,但效率低(因为需要重新渲染)。
如果结构中还包含输入类的DOM:
会产生错误DOM更新=》界面有问题
4、开发中如何选择key
最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表展示,使用index作为key没有问题。
示例:遍历列表以index作为key
如下图:根据初始数据生成虚拟DOM,此时这些虚拟DOM存储在内存中,然后将虚拟DOM转为真实DOM,用户在真实DOM中输入内容,新的数据出现了,老刘,被放到第一个数组中,根据新数据生成新虚拟DOM,虚拟DOM对比算法
遍历列表以id作为key
三、列表过滤
实现前端数据搜索功能
<div id="app">
<input type="text" v-model="keyWorld" />
<ul>
<li v-for="p in filterPersons" :key="p.id">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
1、使用watch
<script>
Vue.config.productionTip = false;
new Vue({
el: "#app",
data: {
keyWorld: "",
persons: [
{
id: 1,
name: "马冬梅",
sex: "女",
age: 18,
},
{
id: 2,
name: "周冬雨",
sex: "女",
age: 19,
},
{
id: 3,
name: "周杰伦",
sex: "男",
age: 20,
},
{
id: 4,
name: "林俊杰",
sex: "男",
age: 21,
},
],
filterPersons: [],
},
watch: {
keyWorld: {
immediate: true,
handler() {
this.filterPersons = this.persons.filter((item) => {
return item.name.indexOf(this.keyWorld) > -1;
});
},
},
},
});
</script>
使用计算属性
<script>
Vue.config.productionTip = false;
new Vue({
el: "#app",
data: {
keyWorld: "",
persons: [
{
id: 1,
name: "马冬梅",
sex: "女",
age: 18,
},
{
id: 2,
name: "周冬雨",
sex: "女",
age: 19,
},
{
id: 3,
name: "周杰伦",
sex: "男",
age: 20,
},
{
id: 4,
name: "林俊杰",
sex: "男",
age: 21,
},
],
},
computed: {
filterPersons() {
return this.persons.filter((item) => {
return item.name.indexOf(this.keyWorld) > -1;
});
},
},
});
</script>
3、使用方法
<div id="app">
<input type="text" v-model="keyWorld" @input="keyChange" />
<ul>
<li v-for="p in filterPersons" :key="p.id">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false;
new Vue({
el: "#app",
data: {
keyWorld: "",
persons: [
{
id: 1,
name: "马冬梅",
sex: "女",
age: 18,
},
{
id: 2,
name: "周冬雨",
sex: "女",
age: 19,
},
{
id: 3,
name: "周杰伦",
sex: "男",
age: 20,
},
{
id: 4,
name: "林俊杰",
sex: "男",
age: 21,
},
],
filterPersons: [],
},
created() {
this.keyChange();
},
methods: {
keyChange() {
this.filterPersons = this.persons.filter((item) => {
return item.name.indexOf(this.keyWorld) > -1;
});
},
},
});
</script>
四、列表排序
实现前端数据搜索和排序功能
<div id="app">
<input type="text" v-model="keyWorld" />
<button @click="sortType=2">升序</button>
<button @click="sortType=1">降序</button>
<button @click="sortType=0">原顺序</button>
<ul>
<li v-for="p in filterPersons" :key="p.id">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
JS部分
<script>
Vue.config.productionTip = false;
new Vue({
el: "#app",
data: {
sortType: 0,
keyWorld: "",
persons: [
{
id: 1,
name: "马冬梅",
sex: "女",
age: 32,
},
{
id: 2,
name: "周冬雨",
sex: "女",
age: 19,
},
{
id: 3,
name: "周杰伦",
sex: "男",
age: 25,
},
{
id: 4,
name: "林俊杰",
sex: "男",
age: 16,
},
],
},
computed: {
filterPersons() {
var arr = this.persons.filter((item) => {
return item.name.indexOf(this.keyWorld) > -1;
});
if (this.sortType) {
arr.sort((p1, p2) => {
return this.sortType == 1 ? p2.age - p1.age : p1.age - p2.age;
});
}
return arr;
},
},
});
</script>