Vue中Transition Group搭配v-if时动画失效的解决方法
修复Vue Transition Group添加v-if后动画失效的问题
我明白你遇到的困扰了——原本正常运行的<transition-group>动画,给它加上v-if判断后突然没了效果。这其实是v-if的工作机制导致的,咱们一步步来搞定它。
问题根源
当你把v-if='article_list.length != 0'加在<transition-group>上时,意味着列表为空时整个transition-group组件会被完全销毁;等数据加载完成后,组件才重新挂载到DOM上。此时组件内部的列表元素属于初始渲染,Vue不会把它们识别成"新进入"的元素,自然就不会触发过渡动画了。
解决方案
这里有两种简单的修复方式,你可以根据需求选择:
方案1:把v-if替换成v-show
v-show不会销毁组件,只是通过CSS的display属性控制显示隐藏。这样transition-group始终存在于DOM中,当数据加载完成后,列表元素的添加会被Vue捕捉到,就能正常触发过渡动画了。
修改后的模板代码:
<template> <div class='main-page-articles'> <!-- 将v-if替换为v-show --> <transition-group name="article-list" class='main-page-news' tag='ul' v-show='article_list.length != 0'> <li class='main-page-article' v-for='article in article_list' v-bind:key='article.title' v-on:click='redirectToArticle(article.primary_key)'> <div class='main-page-article-header'> <img class='main-page-article-img' src='https://www.gamereactor.eu/media/35/stellaris_2063523b.jpg'></img> <div class='main-page-article-title'> <span class='main-page-article-text'> {{article.title}} </span> </div> <div class='main-page-article-info'> <div class='main-page-article-created'> {{article.created}} </div> </div> </div> <div class='main-page-article-body'></div> </li> <li class='main-page-article' v-if='article_list.length != 6' v-for='index in 6 - article_list.length' v-bind:key='index'> </li> </transition-group> <!-- 这里的v-if也同步换成v-show --> <ul class='main-page-news' v-show='article_list.length == 0'> <li class='main-page-article' v-for='index in 6' v-bind:key='index'> <div class='loading-main-article'></div> </li> </ul> </div> </template>
方案2:让transition-group始终挂载,内部控制列表显示
如果你确实需要保留v-if的销毁逻辑(比如性能考量),可以让transition-group始终存在,把v-if的判断移到内部的列表元素上,同时给transition-group加一个动态key,确保数据更新时组件能重新触发动画:
<template> <div class='main-page-articles'> <!-- 移除transition-group上的v-if,添加动态key --> <transition-group name="article-list" class='main-page-news' tag='ul' :key="article_list.length"> <!-- 给真实文章列表加上v-if判断 --> <li class='main-page-article' v-if='article_list.length != 0' v-for='article in article_list' v-bind:key='article.title' v-on:click='redirectToArticle(article.primary_key)'> <div class='main-page-article-header'> <img class='main-page-article-img' src='https://www.gamereactor.eu/media/35/stellaris_2063523b.jpg'></img> <div class='main-page-article-title'> <span class='main-page-article-text'> {{article.title}} </span> </div> <div class='main-page-article-info'> <div class='main-page-article-created'> {{article.created}} </div> </div> </div> <div class='main-page-article-body'></div> </li> <li class='main-page-article' v-if='article_list.length != 0 && article_list.length != 6' v-for='index in 6 - article_list.length' v-bind:key='index'> </li> </transition-group> <ul class='main-page-news' v-if='article_list.length == 0'> <li class='main-page-article' v-for='index in 6' v-bind:key='index'> <div class='loading-main-article'></div> </li> </ul> </div> </template>
额外小提示
你的CSS过渡样式只定义了进入状态,建议补充离开状态的样式,这样列表元素移除时也能有平滑的过渡效果:
.article-list-enter-active, .article-list-leave-active { transition: all 1.5s; } .article-list-enter, .article-list-leave-to { opacity: 0; }
内容的提问来源于stack exchange,提问作者Max Montana
相关产品推荐
相关产品推荐

