vue组件之路之轮播图的实现

预览地址

图片的轮播

假设需要轮播三张图片(1,2,3),以前的思路就如图所示,添加两个节点。通过索引(index)的切换实现组件的无缝轮播。

这种想法的确可行,而且实现出来效果还不错。 缺点在于

  • 大量的dom操作。
  • 代码逻辑相对挺复杂,量也更多。
  • 重构或添加新功能会更麻烦

现在的思路

创建两个组件分别为 carouselcarousel-item

结构如下

<x-carousel :selected.sync="selected">
         <x-carousel-item name="1">
          <div class="box"> 1</div>
         </x-carousel-item>
         <x-carousel-item name="2">
           <div class="box">2</div>
         </x-carousel-item>
         <x-carousel-item name="3">
            <div class="box">3</div>
         </x-carousel-item>
</x-carousel>
复制代码

selected即为显示的内容的name,用sync做一个"双向绑定"。这样子父组件就可以通过 updated钩子和$children来实时通知子组件,从而控制内容的展示。

updated(){
           this.updateChildrens(this.selected)
       }
   methods:{
       updateChildrens(){
           //被选中的那个可以显示了,其他的关闭
       }
   }
复制代码

也就是说 carousel负责数据通信,而carousel-item只需完成动画过渡效果就行了,这样逻辑就非常清晰了。

这里当然就存在动画正向与反向的问题,需要两种方向不同的切入切出的动画。 carousel需要做一次判断然后在updateChildrens的时候就告诉子组件方向。

进入方向的判断

  • 需要一个变量记录上一次的selected数值,假设就为 oldSelectednewSelected
  • 自动轮播是默认正向的(往后播放),到最后一个的时候回到第一个应该也是正向的
  • 圆点(图片索引图标)选取切换,只需判断两次变量的大小就行
  • 方向键切换(箭头图标),和自动轮播同理,方向应时刻和箭头方向一致

解决跳过中间图片的问题

不管轮播图数量多少,这里始终只在两张图里面切换。这样就涉及到一个问题就是会 跳过中间的图片

首先carousel-item有一个默认的图片过渡时间,这里可以通过计算oldSelectednewSelected之间的差值来确定跳过图片的数量。当然也有动画方向的问题。

 clickSelected(newSelected){
               clearInterval(this.timer2)
               if(oldSelected===newSelected)return
               lastSelected = oldSelected
                // .............
               this.‘控制时长的函数’(lastSelected,newSelected)
           },
           
  '控制时长的函数'(lastSelected,newSelected){
               //........
               let newIndex = newSelected 
               let animationDuration = '计时器的间隔时长'
               theIndex = ‘下一个展示的图片索引’
               //.......
             this.duration = duration  
               this.'carousel组件'.forEach(vm=>vm.duration=duration)
               this.$emit('update:selected',names[theIndex])//通知一下父组件将要展示的下一个图片的索引
               if(theIndex===newIndex)return
               this.timer2 = setInterval(()=>{
                   if(theIndex===newIndex){
                       this.clearAndSet()
                   }
                   this.$emit('update:selected',names[theIndex])
                   oldIndex>newIndex?theIndex--:theIndex++
               },duration*animationDuration)
  }        
复制代码

基本就能完成跳过中间图片的这样子的问题了,后面的click改为 hover触发功能就很简单了。

最后是卡片化轮播的实现,这里差不多就是把 selected改为数组而已,固定只出现两个或三个图片。目前还没去做这个功能(好多组件还没写)。后面会更新。

猜你喜欢

转载自juejin.im/post/5c9352f75188252d6d2face4