Vue.js过渡和过渡组动画无效

时间:2017-09-19 18:14:34

标签: vue.js vuejs2 css-transitions

我有一个Vue 2 Carousel组件,使用v-for生成Slide子组件。使用v-show显示和隐藏幻灯片。我无法让幻灯片之间的CSS transition工作。

我尝试在<transition>中包装幻灯片,但mode=out-in什么也没做,我在转换过程中最终在转盘中有两个幻灯片,一个淡入,另一个淡出。当我将幻灯片包装在<transition-group>中时,CSS transition根本不会显示,幻灯片只会被替换。

我查看了transitioning between components,但幻灯片是根据API链接列表生成的,我没有看到将动态生成与此解决方案相结合的方法。

这是JSFiddle with the issue

2 个答案:

答案 0 :(得分:1)

如果您不打算交叉淡化图像(即在任何给定的时间点,屏幕上实际只有一个图像),您可以重新构建代码,例如只有一个<Slide>组件呈现在单次。您只需指定一个动态更新的唯一键,例如您滑块组件的active数据。

您的模板现在看起来像这样:

<div class="carousel-wrapper" id="promotions">
    <transition name="component-fade" mode="out-in">
        <!-- Bind image url dynamically, bind key to active index -->
        <Slide class="slide" :url="imageUrl" :key="active"></Slide>
    </transition>
</div>

imageUrl只是一个计算属性,它通过索引返回图像URL:

imageUrl() {
    return this.list[this.active].url;
}

Slide组件应该像我们需要的那样“哑”:在这种情况下,它只是接收动态绑定的图像URL而已:

<div>
    <img :src="url" class="image">
</div>

注意:

  • 您应使用等于或短于active属性更新的时间间隔的转换持续时间。在您的原始代码中,幻灯片循环播放3秒,但过渡持续时间设置为4秒,导致真正的janky过渡
  • 如果您想要交叉渐变动画,解决方案会更复杂。

这是一个概念验证示例:

Vue.component('Slide', {
  template: `
	<div>
		<img :src="url" class="image">
	</div>`,
  props: ['url']
});

Vue.component('component-2', {
  template: `<div>
                    <p>component 2</p>
                 </div>`
});

new Vue({
  el: '#example',
  template: `
  <div class="carousel-wrapper" id="promotions">
		<transition name="component-fade" mode="out-in">
			<Slide class="slide" :url="imageUrl" :key="active">
			</Slide>
		</transition>
  </div>`,
  data() {
    return {
      list: [{
          url: 'https://static.pexels.com/photos/572741/pexels-photo-572741.jpeg'
        },
        {
          url: 'https://static.pexels.com/photos/575739/pexels-photo-575739.jpeg'
        },
        {
          url: 'https://static.pexels.com/photos/576832/pexels-photo-576832.jpeg'
        }
      ],
      active: 0
    }
  },
  computed: {
    numberOfSlides() {
      return this.list.length - 1
    },
    imageUrl() {
      return this.list[this.active].url;
    }
  },
  created() {
    this.rotate()
  },
  methods: {
    moveSlide(event) {
      this.active = event.srcElement.dataset.slide
      this.list.forEach(el => {
        el.active = false
      })
      this.list[event.srcElement.dataset.slide].active = true
    },
    rotate() {
      if (this.active < this.numberOfSlides) {
        this.active = this.active + 1
      } else {
        this.active = 0
      }
      let _this = this
      setTimeout(_this.rotate, 3000)
    }
  }
});
.carousel-wrapper {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.carousel {}

.dots {
  max-width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  position: absolute;
  bottom: 2em;
  z-index: 1;
}

.dot {
  height: 1em;
  width: 1em;
  margin: 0 1em 0 1em;
  border-radius: 50%;
  background-color: red;
}

.component-fade-enter-active,
.component-fade-leave-active {
  transition: opacity 1s ease;
}

.component-fade-enter,
.component-fade-leave-to {
  opacity: 0;
}

.slide {
  width: 100%;
  height: 650px;
}

.image {
  max-width: 100%;
  max-height: 650px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="example">
</div>

答案 1 :(得分:0)

我认为这是因为您不需要使用v-show

您应该使用<transition name="slide-fade"><slides></slides></transition>,然后在CSS中定义转换。

你应该看到这个doc,它对我有用。