預覽地址css
假設須要輪播三張圖片(1,2,3),之前的思路就如圖所示,添加兩個節點。經過索引(index)的切換實現組件的無縫輪播。html
這種想法的確可行,並且實現出來效果還不錯。
缺點在於vue
建立兩個組件分別爲 carousel
和 carousel-item
git
結構以下github
<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
只需完成動畫過渡效果就好了,這樣邏輯就很是清晰了。dom
這裏固然就存在動畫正向與反向的問題,須要兩種方向不一樣的切入切出的動畫。carousel
須要作一次判斷而後在updateChildrens
的時候就告訴子組件方向。ide
selected
數值,假設就爲 oldSelected
和newSelected
無論輪播圖數量多少,這裏始終只在兩張圖裏面切換。這樣就涉及到一個問題就是會
跳過中間的圖片svg
首先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
觸發功能就很簡單了。
## 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')return let move = {left:'back', right:'go'} this.$parent.'我是父組件的方法'(index,move[direction]) }
## 還沒有完善的細節
其實我認爲動畫仍是有一點點瑕疵的,後面會在css上修改一下,順便簡單調整樣式和更換動態svg。最後,有待增強的地方但願大佬們指出來交流,要是以爲還行的話,給個人項目點個star就是最好的了。