Vue.js 中不需要的动画错误
Unwanted animation bug in Vue.js
这是一个不需要的动画错误,看起来很正常,但我希望 <input v-model="todo"/>
中的元素具有动画效果。问题是每次我按 add 按钮添加 todo 名称 (<input v-model="todo"/>
),最后一个元素 'last' 运行动画。
P.s。我尽量保持代码简单。
Vue.createApp({
data() {
return {
todo: "",
todo_list: ['last'],
};
},
methods: {
add() {
this.todo_list.unshift(this.todo);
console.log(this.todo_list);
},
remove(index) {
this.todo_list.splice(index, 1);
},
},
}).mount('#app');
.list-enter-active,
.list-leave-active {
transition: all 200ms ease-out;
}
.list-enter-from {
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateX(20px);
}
article {
width: 50%;
padding: 10px;
background-color: #dddddd;
border: 1px solid #cfcfcf;
border-radius: 5px;
margin-block: 10px
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<input type="text" v-model="todo" /> <button @click="add">add</button>
<transition-group name="list" tag="section">
<article v-for="(todo, index) in todo_list" :key="index" @click="remove(index)">
<span>{{ todo }}</span>
</article>
</transition-group>
</div>
您遇到此问题的原因是您将 index
用作 key
。
如果您将元素添加到列表的末尾,那就没问题了。
但由于您将它添加到开头,它会导致您看到的问题。
我建议您让每个 todo
成为一个对象,并为每个对象添加一个唯一标识符。这可以是您递增的简单整数。然后你可以使用 属性 作为 key
.
例子
let id = 1;
Vue.createApp({
data() {
return {
todo: "",
todo_list: [{
id: id++,
value: 'last'
}],
};
},
methods: {
add() {
const todo = {
id: id++,
value: this.todo
}
this.todo_list.unshift(todo);
},
remove(index) {
this.todo_list.splice(index, 1);
},
},
}).mount('#app');
.list-enter-active,
.list-leave-active {
transition: all 200ms ease-out;
}
.list-enter-from {
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateX(20px);
}
article {
width: 50%;
padding: 10px;
background-color: #dddddd;
border: 1px solid #cfcfcf;
border-radius: 5px;
margin-block: 10px
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<input type="text" v-model="todo" /> <button @click="add">add</button>
<transition-group name="list" tag="section">
<article v-for="(todo, index) in todo_list" :key="todo.id" @click="remove(index)">
<span>{{ todo.value }}</span>
</article>
</transition-group>
</div>
这是一个不需要的动画错误,看起来很正常,但我希望 <input v-model="todo"/>
中的元素具有动画效果。问题是每次我按 add 按钮添加 todo 名称 (<input v-model="todo"/>
),最后一个元素 'last' 运行动画。
P.s。我尽量保持代码简单。
Vue.createApp({
data() {
return {
todo: "",
todo_list: ['last'],
};
},
methods: {
add() {
this.todo_list.unshift(this.todo);
console.log(this.todo_list);
},
remove(index) {
this.todo_list.splice(index, 1);
},
},
}).mount('#app');
.list-enter-active,
.list-leave-active {
transition: all 200ms ease-out;
}
.list-enter-from {
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateX(20px);
}
article {
width: 50%;
padding: 10px;
background-color: #dddddd;
border: 1px solid #cfcfcf;
border-radius: 5px;
margin-block: 10px
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<input type="text" v-model="todo" /> <button @click="add">add</button>
<transition-group name="list" tag="section">
<article v-for="(todo, index) in todo_list" :key="index" @click="remove(index)">
<span>{{ todo }}</span>
</article>
</transition-group>
</div>
您遇到此问题的原因是您将 index
用作 key
。
如果您将元素添加到列表的末尾,那就没问题了。
但由于您将它添加到开头,它会导致您看到的问题。
我建议您让每个 todo
成为一个对象,并为每个对象添加一个唯一标识符。这可以是您递增的简单整数。然后你可以使用 属性 作为 key
.
例子
let id = 1;
Vue.createApp({
data() {
return {
todo: "",
todo_list: [{
id: id++,
value: 'last'
}],
};
},
methods: {
add() {
const todo = {
id: id++,
value: this.todo
}
this.todo_list.unshift(todo);
},
remove(index) {
this.todo_list.splice(index, 1);
},
},
}).mount('#app');
.list-enter-active,
.list-leave-active {
transition: all 200ms ease-out;
}
.list-enter-from {
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateX(20px);
}
article {
width: 50%;
padding: 10px;
background-color: #dddddd;
border: 1px solid #cfcfcf;
border-radius: 5px;
margin-block: 10px
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<input type="text" v-model="todo" /> <button @click="add">add</button>
<transition-group name="list" tag="section">
<article v-for="(todo, index) in todo_list" :key="todo.id" @click="remove(index)">
<span>{{ todo.value }}</span>
</article>
</transition-group>
</div>