ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] #### CubeUi Tab 滑屏切换组件 * [ ] 核心算法 滑动的距离 = 滑动的X坐标 / 滑动区域宽度 * tab导航栏宽度 1. 定义组件 ~~~ <template> <div class="tab"> <!-- tabbar 导航切换区 --> <cube-tab-bar v-model="selectedLabel" :data="tabs" :showSlider=true :useTransition=false class="border-bottom-1px" ref="tabbar" > </cube-tab-bar> <!-- swiper 滑动区 --> <div class="silde-wrapper"> <cube-slide :loop=false :showDots=false :autoPlay=false :initialIndex="index" @change="onChange" @scroll="onScroll" :options="scrollOptions" ref="slide" > <cube-slide-item v-for="(tab, index) in tabs" :key="index"> <!-- tab.component 组件 tab.data 数据 --> <component :is="tab.component" :data="tab.data"></component> </cube-slide-item> </cube-slide> </div> </div> </template> <script type="text/ecmascript-6"> export default { name: "tab", props: { tabs: { type: Array, default() { return {} } }, initIndex: { type: Number, default: 0 } }, data () { return { index: this.initIndex, // BScroll 配置 scrollOptions: { probeType: 3, //滚动动画运行过程中实时派发 scroll 事件 listenScroll: true, // 监听 BScroll 滚动 directionLockThreshold: 0 // 锁定滚动 } } }, methods: { // slide 滑动结束会派发当前索引 onChange(current) { this.index = current }, // slide 滚动时派发 onScroll(pos) { // 横向滚动距离 let posX = Math.abs(pos.x) // tabbar 宽度 const tabbarWidth = this.$refs.tabbar.$el.clientWidth // slide 宽度 const slideWidth = this.$refs.slide.slide.scrollerWidth // 计算滚动距离 = posX / slideWidth * tabbarWidth const transForm = posX / slideWidth * tabbarWidth // 改变 cube-tab-bar 组件的下划线的 transformX this.$refs.tabbar.setSliderTransform(transForm) } }, computed: { // 计算索引 selectedLabel: { get() { return this.tabs[this.index].label }, set(newVal) { this.index = this.tabs.findIndex((value) => { return value.label === newVal }) } } } } </script> <style lang="stylus" rel="stylesheet/stylus" scoped> .tab display flex flex-direction column height 100% >>> .cube-tab color #666 font-size 30px padding 20px 0 .silde-wrapper flex 1 overflow hidden </style> ~~~ ***** 2. 外部调用 ~~~ <template> <div id="app"> <v-header /> <tab :tabs="tabs" :initIndex="currentIndex" /> </div> </template> <script> import vheader from '@/components/vheader' import tab from '@/components/tab/tab' import { goods } from '@/api' import good from '@/components/goods/goods' import rating from '@/components/ratings/rating' import seller from '@/components/seller/seller' export default { name: 'app', data() { return { currentIndex: 0 } }, computed: { tabs() { return [ { label: '商品', component: good }, { label: '评论', component: rating }, { label: '商家', component: seller } ] } }, components: { 'v-header': vheader, tab } } </script> <style lang="stylus"> #app width 100% height 100% overflow hidden </style> ~~~