如何在 Vue 中删除列表项时为列表项设置动画
Posted
技术标签:
【中文标题】如何在 Vue 中删除列表项时为列表项设置动画【英文标题】:How to animate list items in Vue when one is removed 【发布时间】:2018-10-22 23:28:10 【问题描述】:我有一个垂直的项目列表,每个项目都可以删除。我将我的项目放在一个过渡组中,并为它们创建了简单的不透明度和变换过渡。已移除元素上的转换按预期工作,但是如果我移除一个未放置在底部的元素,则下方的元素只会跳起来并在没有任何转换的情况下取代它。我找不到针对这种行为的方法。 我想要的只是下面的元素平滑地向上滑动。
有没有什么办法可以通过使用 css transitipms 和 Vue 的动画钩子来实现这个效果?
这是一个演示:https://jsfiddle.net/gcp18nq0/
模板:
<div id="app">
<div class="form">
<label for="name">Name</label>
<input type="text" id="name" v-model="name">
<button @click="addPlayer">Add player</button>
</div>
<div class="players">
<transition-group name="player">
<div class="panel" v-for="player in players" :key="player.id">
<h2>
player.name
<span class="remove" @click="removePlayer(player.id)">Remove</span>
</h2>
</div>
</transition-group>
</div>
</div>
脚本:
data()
return
name: "",
players: [
id: 1, name: 'Player1',
id: 2, name: 'Player2',
id: 3, name: 'Player3',
]
,
methods:
addPlayer: function ()
//,,,,
,
removePlayer: function (playerId)
//...
);
CSS
.form
margin:0 auto;
width:400px;
.panel
width: 400px;
margin: 10px auto;
overflow: hidden;
border: 1px solid;
text-align: center;
.remove
float: right;
cursor: pointer;
text-decoration: underline;
font-size: 12px;
vertical-align: bottom
.player-enter,
.player-leave-to
/* .fade-leave-active below version 2.1.8 */
opacity: 0;
.player-enter
transform: translateY(30%);
.player-leave-to
transform: translateX(30%);
.player-enter-active,
.player-leave-active
transition: all 1.5s;
.player-move
transition: all 1.5s;
我发现的唯一工作方式是在“player-leave-active”状态下添加 position:absolute,但由于元素折叠,它会改变其垂直位置,这不是预期的效果。我也尝试改变高度,但是在高度设置为 0 后,下面的元素仍然会向上跳跃一点。 我确信这可以通过 jQuery 轻松实现,但我相信应该有一种方法可以在没有 js 的情况下做到这一点。
提前感谢您!
附言这是我在这里的第一篇文章,所以我希望它解释得足够清楚。
【问题讨论】:
【参考方案1】:所以我对你的小提琴做了一些小的调整:https://jsfiddle.net/gcp18nq0/1/,希望这就是你想要的。
根据Vue documentation,最重要的变化是在.panel
类上设置display: inline-block
:
一个重要的注意事项是这些 FLIP 过渡不适用于 元素设置为 display: inline。作为替代方案,您可以使用 display: inline-block 或将元素放置在 flex 上下文中。
new Vue(
el: "#app",
data()
return
name: "",
players: [
id: 1,
name: 'Batman'
,
id: 2,
name: 'Robin'
,
id: 3,
name: 'Superman'
,
id: 4,
name: 'Spiderman'
,
]
,
methods:
addPlayer: function()
const newPlayer =
id: this.players.length + 1,
name: this.name,
;
this.players.push(newPlayer);
,
deletePlayer: function(playerId)
let playerToRemove = this.players.find((player) =>
return player.id === playerId;
);
let playerIndex = this.players.indexOf(playerToRemove);
this.players.splice(playerIndex, 1);
);
.form
margin: 0 auto;
width: 400px;
.panel
width: 400px;
margin: 6px auto;
overflow: hidden;
border: 1px solid;
text-align: center;
transition: all 1s;
display: inline-block;
.players
position: relative;
text-align: center;
.remove
float: right;
cursor: pointer;
text-decoration: underline;
font-size: 12px;
vertical-align: bottom
.player-enter,
.player-leave-to
opacity: 0;
.player-enter
transform: translateY(30%);
.player-leave-to
transform: translateX(300%);
.player-leave-active
position: absolute;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<div class="form">
<label for="name">Name</label>
<input type="text" id="name" v-model="name">
<button @click="addPlayer">Add player</button>
</div>
<div class="players">
<transition-group name="player" tag="div">
<div class="panel" v-for="player in players" :key="player.id">
<h2>
player.name
<span class="remove" @click="deletePlayer(player.id)">Remove</span>
</h2>
</div>
</transition-group>
</div>
</div>
【讨论】:
这里的另一个增强功能是在整个列表高度发生变化时也让父容器平滑过渡。现在,当行出现/消失时,父容器会跳转。以上是关于如何在 Vue 中删除列表项时为列表项设置动画的主要内容,如果未能解决你的问题,请参考以下文章