You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue封装可复用TransitionGroup组件过渡动画未按预期生效

问题根因

Vue单文件组件的scoped样式实现隔离的逻辑是:给当前组件自身渲染的DOM元素加唯一哈希属性(类似data-v-7ba5bd90),同时给所有样式选择器末尾追加对应的属性选择器,确保样式只会命中当前组件的元素。
你封装的过渡组件中,<slot>位置渲染的li元素是父组件ProductList的模板内容,属于父组件渲染的DOM,不会被加上当前过渡组件的哈希标记。因此你写在过渡组件scoped块里的.list-enter-from这类选择器,编译后会变成.list-enter-from[data-v-7ba5bd90],根本匹配不到插槽传进来的li元素,动画自然触发不了。而把同样的样式写在ProductList的scoped块里时,li元素带有ProductList的哈希属性,选择器可以正常匹配,所以动画能正常运行。

修复方案

方案1:用深度选择器穿透作用域(推荐)

使用:deep()伪类修改封装组件内的过渡样式,让选择器可以匹配到插槽传入的子元素,既保留样式隔离的特性,又不需要在业务组件重复写样式,还能用上你定义的duration属性:

<template>
  <transition-group name="list" tag="ul">
    <slot></slot>
  </transition-group>
</template>

<script>
export default {
  props: {
    duration: {
      type: Number,
      default: 2,
    },
  },
};
</script>

<style scoped>
:deep(.list-enter-from) {
  opacity: 0;
}

:deep(.list-enter-active) {
  transition: opacity v-bind(duration + 's') ease-in;
}

:deep(.list-enter-to) {
  opacity: 1;
}
</style>

方案2:使用全局样式

如果需要在项目多个地方复用这套过渡效果,可以去掉<style>标签的scoped属性,把过渡样式设为全局:

<style>
/* 无scoped标识,样式全局生效 */
.list-enter-from {
  opacity: 0;
}

.list-enter-active {
  transition: opacity 1s ease-in;
}

.list-enter-to {
  opacity: 1;
}
</style>

注意全局样式容易出现类名冲突,建议给过渡名加专属前缀,比如把name="list"改成name="custom-fade",对应类名同步修改即可。

额外提醒:使用<transition-group>时一定要给循环渲染的子元素设置唯一key,否则过渡动画会出现异常,你当前的代码里已经给li绑定了product.id作为key,这部分符合要求。

内容的提问来源于stack exchange,提问作者qweezz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 02:15:26