vue-for注意点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<form>
<input type="text" v-model="name">
<input type="submit" @click.prevent="add">
</form>
<ul>
<li v-for="(person,index) in persons">
<input type="checkbox">
<span>{{index}}--{{person.name}}</span>
</li>
</ul>
</div>
<script>
let vue=new Vue({
el:"#app",
data:{
name:"",
persons:[{
name:"zs"
},{
name:"ls"
},{
name:"ww"
}],
},
methods:{
add() {
let newPerson={name:this.name};
this.persons.push(newPerson);
this.name='';
}
}
});
</script>
</body>
</html>
add() {
let newPerson={name:this.name};
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name='';
}
为什么会出现这个问题?
因为v-for是采用“就地复用”的原则提高渲染性能的
- v-for在渲染元素的时候会先查看有没有需要渲染的元素
- 如果缓存中没有渲染的元素,就会创建一个新的放到缓存中进行渲染;如果缓存中有需要渲染的元素,则不会创建新的,直接复用原来的数据
注意点:在vue中只要数据发生了变化,则会自动重新渲染,“数据驱动界面”
怎样解决这个问题?
给每一个渲染的元素加上一个key,key的取值必须为独一无二的
<li v-for="(person,index) in persons" :key="person.id">
同时创建元素时给每个persons里的对象添加一个独一无二的ID,实现代码如下:
<script>
let vue=new Vue({
el:"#app",
data:{
name:"",
persons:[{
name:"zs",id:1
},{
name:"ls",id:2
},{
name:"ww",id:3
}],
},
methods:{
add() {
let lastPerson=this.persons[this.persons.length-1];
console.log(lastPerson.id);
let newPerson={name:this.name,id:lastPerson.id+1};
console.log(newPerson);
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name='';
}
}
});
</script>
注意点:不能用index作为:key,因为index虽然是以独一无二的,但是可以是同步变化的
具有动画的添加和删除案例(列表动画)
- 引出transition-group
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
.v-enter{
opacity: 0;
}
.v-enter-active{
transition: all 3s;
}
.v-enter-to{
opacity: 1;
}
.v-leave{
opacity: 1;
}
.v-leave-active{
transition: all 3s;
}
.v-leave-to{
opacity: 0;
}
</style>
</head>
<body>
<div id="app">
<form>
<input type="text" v-model="name">
<input type="submit" @click.prevent="add">
</form>
<ul>
<transition-group appear>
<li v-for="(person,index) in persons" :key="person.id" @click.prevent="del(index)">
<input type="checkbox">
<span>{{index}}--{{person.name}}</span>
</li>
</transition-group>
</ul>
</div>
<script>
let vue=new Vue({
el:"#app",
data:{
name:"",
persons:[{
name:"zs",id:1
},{
name:"ls",id:2
},{
name:"ww",id:3
}],
},
methods:{
add() {
let lastPerson=this.persons[this.persons.length-1];
console.log(lastPerson.id);
let newPerson={name:this.name,id:lastPerson.id+1};
console.log(newPerson);
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name='';
},
del(index){
this.persons.splice(index, 1);
}
}
});
</script>
</body>
</html>
列表动画的注意点
- <transition-group>标签会自动给需要做动画的元素添加一个
<span></span>
将其包起来,但是这样是不合理的,我们可以通过在transition-group标签上添加tag属性来指定添加什么元素作为需要执行动画的父元素
我们删除原有的ul标签,给transition标签添加tag="ul"则可达到一样的效果
<!-- <ul>-->
<transition-group appear tag="ul">
<li v-for="(person,index) in persons" :key="person.id" @click.prevent="del(index)">
<input type="checkbox">
<span>{{index}}--{{person.name}}</span>
</li>
</transition-group>
<!-- </ul>-->
- 列表动画引起的key混乱
添加了tag之后新增元素就没有动画了,反而第一次添加的那个数据发生动画,这个现象叫做“动画混乱”
为什么会发生这种想现象呢?因为最后一个元素的ID一直没有变,所以新添加的元素的key都是一样的,又由于v-for“就地复用”的原则,就发生了动画混乱
解决方案,代码如下:
将最后一个元素的ID直接设置给data中的add,在执行add方法时,首先将this.id自增,然后直接将自增后的id赋值给新增的person的id,就可以解决动画混乱的问题了
<script>
let vue=new Vue({
el:"#app",
data:{
name:"",
persons:[{
name:"zs",id:1
},{
name:"ls",id:2
},{
name:"ww",id:3
}],
id:3
},
methods:{
add() {
this.id++;
// let lastPerson=this.persons[this.persons.length-1];
console.log(id);
let newPerson={name:this.name,id:id};
console.log(newPerson);
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name='';
},
del(index){
this.persons.splice(index, 1);
}
}
});
</script>