仿照B站制作的滑動導航功能,進行了部分優化,例如可定制默認選中元素,並將選中元素居中顯示,可動態更改數據,可定制回調函數取的下標和選中元素內容,可根據需求制作N級聯動
已開發成插件,使用方法與源碼請前往github------傳送門
注:此項目依托於swiper
vue-tabbar-slide.vue
template:
<div class="tabbar-slide-wrapper"> <div class="swiper-container" :class="options.container"> <div class="swiper-wrapper"> <div :style="[slideStyle, {'color': (index == slideOptions.slideIndex) ? slideStyle.checkedColor : slideStyle.color}]" :class="[index == slideOptions.slideIndex ? 'swiper-slide-checked' : '', 'swiper-slide']" v-for="(item, index) in options.slideData" :key="index">{{item}}</div> <!-- 下划線 --> <div :style="{width: slideStyle.width, height: downLineStyle.downLineHeight, background: downLineStyle.downLineColor}" ref="slideDownLine" class="slide-down-line"></div> </div> </div> <div class="tabbar-slide-container"></div> </div>
script:
import Swiper from 'swiper' import '../../node_modules/swiper/dist/css/swiper.min.css' export default { name: 'vueTabbarSlide', props: ['options'], data () { return { mySwiper: null, //數據 slideArr: this.options.slideData || ['slide1', 'slide2', 'slide3', 'slide4', 'slide5', 'slide6', 'slide7', 'slide8', 'slide9', 'slide10', 'slide11', 'slide12', 'slide13'], //樣式 slideStyle: { //寬度 width: this.options.width || '80px', //高度 height: this.options.height || '40px', //垂直高度 lineHeight: this.options.height || '40px', //文本排列方式 textAlign: this.options.textAlign || 'center', //字體大小 fontSize: this.options.fontSize || '14px', //字體格式 fontFamily: this.options.fontFamily || 'Microsoft YaHei', //默認字體顏色 color: this.options.color || '#333', //選中字體顏色 checkedColor: this.options.checkedColor || '#00a0e9' }, downLineStyle: { //下划線高度 downLineHeight: this.options.downLineHeight || '2px', //下划線顏色 downLineColor: this.options.downLineColor || '#00a0e9', }, //選項 slideOptions: { slideIndex: this.options.index || 0 }, //下划線 slideDownLine: null } }, watch: { options: { //此處不要用箭頭函數,this會跑偏 ^_^ handler: function(newValue, oldValue) { if (this.mySwiper) { this.mySwiper.destroy(true, false) } this.mySwiper = new Swiper(`.${this.options.container}`, { slidesPerView: "auto", freeMode: true, freeModeMomentumRatio: 0.5, observer: true, observeParents: false, on: { init: () => { //默認選中 this.slideOptions.slideIndex = this.options.index || 0 //下划線 this.$refs.slideDownLine.style.transform = `translateX(${this.slideOptions.slideIndex*parseInt(this.slideStyle.width)}px)` //回調函數 this.$emit("callback", event, this.slideOptions.slideIndex, this.options.slideData[this.slideOptions.slideIndex]) }, tap: () => { //滑動時間 this.mySwiper.setTransition(300) //滑動 this.slide(swiperWidth, maxTranslate, maxWidth) //更改class this.slideOptions.slideIndex = this.mySwiper.clickedIndex //下划線 this.$refs.slideDownLine.style.transform = `translateX(${this.slideOptions.slideIndex*parseInt(this.slideStyle.width)}px)` //回調函數 this.$emit("callback", event, this.mySwiper.clickedIndex, event.target.innerText) } } }); //swiper可視寬度 const swiperWidth = this.mySwiper.width //swiper最大移動距離 const maxTranslate = swiperWidth - (parseInt(this.options.width) * this.options.slideData.length) // const maxWidth = -maxTranslate + swiperWidth / 2 }, deep: true } }, methods: { slide(swiperWidth, maxTranslate, maxWidth) { //點擊的slide const slide = this.mySwiper.slides[this.mySwiper.clickedIndex] //點擊的slide offsetLeft距離瀏覽器左邊距離 const slideLeft = slide.offsetLeft //點擊的slide的可視寬度 const slideWidth = slide.clientWidth // 被點擊slide的中心點 const slideCenter = slideLeft + slideWidth / 2 //當中心點距離少於一半寬度時 if (slideCenter < swiperWidth / 2) { this.mySwiper.setTranslate(0) } else if (slideCenter > maxWidth) { this.mySwiper.setTranslate(maxTranslate) } else { const nowTlanslate = slideCenter - swiperWidth / 2 this.mySwiper.setTranslate(-nowTlanslate) } //選中顏色 slide.style.color = this.downLineStyle.downLineColor } } }
App.vue
template:
<div id="app"> <vue-tabbar-slide :options="options" @callback="callback"></vue-tabbar-slide> <vue-tabbar-slide1 :options="options1" @callback="callback1"></vue-tabbar-slide1> <div @click="getData">點擊獲取數據</div> <div>第一行下標及數據{{callbackHtml}},<br>第二行下標及數據{{callbackHtml1}}</div> </div>
script:
import vueTabbarSlide from './lib/vueTabbarSlide' export default { name: 'app', data () { return { options: { container: 'mySlide1', slideData: [], width: '80px', index: 1 }, options1: { container: 'mySlide2', slideData: [], width: '80px', index: 1 }, callbackHtml: '', callbackHtml1: '' } }, components: { vueTabbarSlide: vueTabbarSlide, vueTabbarSlide1: vueTabbarSlide }, methods: { getData () { this.options.slideData = ['data1', 'data2', 'data3', 'data4', 'data5', 'data6', 'data7', 'data8', 'data9', 'data10'] this.options1.slideData = ['data11', 'data21', 'data31', 'data41', 'data51', 'data61'] }, callback (event, index, val) { this.callbackHtml = index + ';' + val }, callback1 (event, index, val) { this.callbackHtml1 = index + ';' + val }, } }
在使用中有問題請先去github中查看是否更新到最新版本
如果在新版本中未解決,歡迎您在此或github中給我issure,這樣會讓我開心很長時間,我也會在第一時間認真解決您的問題
最后,感謝您閱讀至此。