vue组件之轮播图的实现
預覽地址
圖片的輪播
假設需要輪播三張圖片(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只需完成動畫過渡效果就行了,這樣邏輯就非常清晰了。
這里當然就存在動畫正向與反向的問題,需要兩種方向不同的切入切出的動畫。 carousel需要做一次判斷然后在updateChildrens的時候就告訴子組件方向。
進入方向的判斷
- 需要一個變量記錄上一次的selected數值,假設就為 oldSelected 和newSelected
- 自動輪播是默認正向的(往后播放),到最后一個的時候回到第一個應該也是正向的
- 圓點(圖片索引圖標)選取切換,只需判斷兩次變量的大小就行
- 方向鍵切換(箭頭圖標),和自動輪播同理,方向應時刻和箭頭方向一致
解決跳過中間圖片的問題
不管輪播圖數量多少,這里始終只在兩張圖里面切換。這樣就涉及到一個問題就是會 跳過中間的圖片
首先carousel-item有一個默認的圖片過渡時間,這里可以通過計算oldSelected 和newSelected之間的差值來確定跳過圖片的數量。當然也有動畫方向的問題。
clickSelected(newSelected){clearInterval(this.timer2)if(oldSelected===newSelected)returnlastSelected = 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)returnthis.timer2 = setInterval(()=>{if(theIndex===newIndex){this.clearAndSet()}this.$emit('update:selected',names[theIndex])oldIndex>newIndex?theIndex--:theIndex++},duration*animationDuration)} 復制代碼基本就能完成跳過中間圖片的這樣子的問題了,后面的click改為 hover觸發功能就很簡單了。
Card卡片化
需要默認三個同時出現的圖片,這意味著需要一個數組。 但是依然不需要改變selected的數據類型(還是字符串)。這種情況用傳遞數組只會添加許多不必要的麻煩和降低性能,像是需要做深拷貝,遍歷判斷這類的。 因為這個應該出現的圖片的數組里面的index都是連號的。這個判斷只需讓子組件來做就行了。現在在carousel-item通過計算得到一個數組
this.cardSelected = [selected-1,selected,selected+1] if(`最后一張圖`){//..... }else if(`第一張圖`){} 復制代碼現在實時顯示的三張圖片的數組已經有了,我只需要分配好他們的位置(左邊,中間,右邊
'我是決定位置的函數'(){let [index,position] = [this.cardSelected.indexOf(Number(this.name)),['left','main','right']]return `position-${position[index]}` } 復制代碼簡單的兩行就搞定了。
然后綁定一下
:class="{......,[我是決定位置的函數]:card}"> 復制代碼剩下的定位還是動畫什么的,都可以交給css去完成了。
&.position-left{width: 50%;position: absolute;top: 0;left: -10px;transform:scale(0.82);}&.position-main{width: 50%;transform: translateX(50%);position: relative;z-index: 3;}&.position-right{transform: translateX(100%) scale(0.82);width: 50%;position: absolute;top: 0;left: 10px;} 復制代碼最后就是點擊兩側圖片會切換
調用父組件的方法就ok了
'調用父組件的方法'(){let [direction,index] = [this.'我是決定位置的函數'.slice(9,16),this.$parent.selectedIndex]if(direction==='main')returnlet move = {left:'back', right:'go'}this.$parent.'我是父組件的方法'(index,move[direction])} 復制代碼尚未完善的細節
其實我認為動畫還是有一點點瑕疵的,后面會在css上修改一下,順便簡單調整樣式和更換動態svg。最后,有待加強的地方希望大佬們指出來交流,要是覺得還行的話,給我的項目點個star就是最好的了。
轉載于:https://juejin.im/post/5c9352f75188252d6d2face4
總結
以上是生活随笔為你收集整理的vue组件之轮播图的实现的全部內容,希望文章能夠幫你解決所遇到的問題。