预览地址 https://jumodada.github.io/vueXin/
图片的轮播
假设需要轮播三张图片 (1,2,3), 以前的思路就如图所示, 添加两个节点. 通过索引(index) 的切换实现组件的无缝轮播.
这种想法的确可行, 而且实现出来效果还不错. 缺点在于
大量的 dom 操作.
代码逻辑相对挺复杂, 量也更多.
重构或添加新功能会更麻烦
现在的思路
创建两个组件分别为 carousel 和 carousel-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 只需完成动画过渡 https://cn.vuejs.org/v2/guide/transitions.html 效果就行了, 这样逻辑就非常清晰了.
这里当然就存在动画正向与反向的问题, 需要两种方向不同的切入切出的动画. carousel 需要做一次判断然后在 updateChildrens 的时候就告诉子组件方向.
进入方向的判断
需要一个变量记录上一次的 selected 数值, 假设就为 oldSelected 和 newSelected
自动轮播是默认正向的(往后播放), 到最后一个的时候回到第一个应该也是正向的
圆点 (图片索引图标) 选取切换, 只需判断两次变量的大小就行
方向键切换(箭头图标), 和自动轮播同理, 方向应时刻和箭头方向一致
解决跳过中间图片的问题
不管轮播图数量多少, 这里始终只在两张图里面切换. 这样就涉及到一个问题就是会 跳过中间的图片
首先 carousel-item 有一个默认的图片过渡时间, 这里可以通过计算 oldSelected 和 newSelected 之间的差值来确定跳过图片的数量. 当然也有动画方向的问题.
- 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 改为数组而已, 固定只出现两个或三个图片. 目前还没去做这个功能(好多组件还没写). 后面会更新.
来源: https://juejin.im/post/5c9352f75188252d6d2face4