Vue 仿B站滑动导航
仿照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,这样会让我开心很长时间,我也会在第一时间认真解决您的问题
最后,感谢您阅读至此。
posted on 2018-05-07 15:20 bling_bling 阅读(5150) 评论(0) 编辑 收藏 举报