Vue动态组件导致<transition appear>页面刷新时重复触发如何解决?
问题原因
这个异常是两个常见的渲染逻辑叠加导致的:
- 你当前用
index作为v-for的key,如果slices是异步获取的数据,刷新页面时会触发两次渲染:第一次是页面初始化slices为空/初始值时的渲染,第二次是异步拿到完整数据后的重渲染,两次都会命中transition的appear触发规则,导致动画重复执行。 <transition>的appear属性默认会在组件每次挂载到DOM时都触发入场动画,动态组件在数据更新触发销毁重建时,就会重复触发appear动画。
另外你贴出的代码存在两处语法错误:component-wrapper的class属性少了闭合引号,:key绑定也少了闭合引号,建议先修正避免其他异常。
解决方案
第一步:替换v-for的key值
不要用索引作为key,换成slice的唯一标识(比如slice.id、slice.slice_id这类全局唯一的字段),避免数据更新时组件不必要的销毁重建:
<div class="component-wrapper" v-for="slice in slices" :key="slice.id" > <component :is="slice.slice_type" :slice="slice" /> </div>
第二步:控制appear的触发时机
通过路由信息判断当前是路由跳转进入还是刷新页面进入,只在路由跳转场景启用appear动画:
Vue3 写法
<script setup> import { ref } from 'vue' import { useRoute } from 'vue-router' const route = useRoute() // 路由跳转进入时from.name存在,刷新页面时from为空 const enableAppear = ref(!!route.from?.name) </script> <template> <transition name="slide-in" :appear="enableAppear"> <!-- 首个需要动画的组件内容 --> </transition> </template>
Vue2 写法
<script> export default { data() { return { enableAppear: !!this.$route.from?.name } } } </script>
备选方案:异步数据场景延后渲染
如果slices确实是异步接口返回的数据,可以等数据加载完成后再渲染动态组件,从根源避免两次渲染:
<template> <!-- 等slices加载完成再渲染 --> <div v-if="slices.length"> <div class="component-wrapper" v-for="(slice, index) in slices" :key="slice.id" > <!-- 只给首个组件加动画 --> <transition name="slide-in" :appear="index === 0 && enableAppear"> <component :is="slice.slice_type" :slice="slice" /> </transition> </div> </div> </template>
内容的提问来源于stack exchange,提问作者josjo
相关产品推荐
相关产品推荐

