前言:在使用uni-app组件时,需求方要求点击头部的tab切换时,首尾两个点击就在最前面和最后面高亮显示即可,中间的要求选中哪个tab哪个tab就在滑到最中间显示。效果图如下: 

自定义tab滑动切换

一、代码实现: 

<template>
    <!-- tab切换 -->
    <view class="my-tab" ref="myTabRef">
        <view class="my-tab-item" v-for="(item, index) in tabs" :ref="`tab${item.name}Ref`" :class="{ active: item.name === activeItem }">
            <view class="my-tab-text" @click="tabClick(item)">{{ item.label }}</view>
        </view>
    </view>
</template>

<script>
export default {
    name: 'my-tab',
    data() {
        return {
            activeItem: 'tabOne',
            tabs: [
                {
                    name: 'tabOne',
                    label: 'tab切换显示1',
                },
                {
                    name: 'tabTwo',
                    label: 'tab切换显示2',
                },
                {
                    name: 'tabThree',
                    label: 'tab切换显示3',
                },
                {
                    name: 'tabFour',
                    label: 'tab切换显示4',
                },
                {
                    name: 'tabFive',
                    label: 'tab切换显示5',
                },
            ],
        };
    },
    methods: {
        // tab点击
        tabClick(item) {
            this.activeItem = item.name;
            // 触发滑动方法
            this.scrollLeftTo(item.name);
        },
        // 滑动
        scrollLeftTo(name) {
            const ref = `tab${name}Ref`;
            // 获取myTabRef的DOM元素,即类名为my-tab的标签
            const nav = this.$refs.myTabRef.$el;
            // 获取当前点击的某一个tab的的DOM元素,即类名为my-tab-item的标签
            const title = this.$refs[ref][0].$el;
            // 计算位移偏差
            const to = title.offsetLeft - (nav.offsetWidth - title.offsetWidth) / 2;
            nav.scrollLeft = to;
        },
    },
};
</script>

<style lang="scss">
    .my-tab {
        height: 88rpx;
        background: #FFFFFF;
        line-height: 88rpx;
        display: flex;
        overflow-x: scroll;
        padding-right: 40rpx;
        scroll-behavior: smooth; //平稳的滑动效果

        .my-tab-item {
            padding: 0 24rpx;
            color: #999999;
            height: 88rpx;
            text-align: center;
            flex: 1 0 auto;

            &.active {
                color: #333333;

                .my-tab-text {
                    position: relative;

                    &::after {
                        position: absolute;
                        left: 50%;
                        bottom: 0;
                        content: '';
                        width: 220rpx;
                        height: 4rpx;
                        background: linear-gradient(180deg, #649AFC 0%, #5180F4 100%);
                        opacity: 1;
                        border-radius: 2rpx;
                        transform: translateX(-50%);
                    }
                }
            }
        }
    }
    // 隐藏滚动条
    ::-webkit-scrollbar {
        height: 0;
        width: 0;
        color: transparent;
    }
</style>

二、知识点:

对于ref的具体介绍我在照片文章有提到:vue.js使用this[ ]()动态获取方法_Lemon今天学习了吗的博客-CSDN博客_vue获取this 

vm.$refs:获取页面中所有含有ref属性的DOM元素(普通元素)。

                  获取组件实例 ,可以使用组件的所有方法 (使用在组件上)。 

如this.$refs.myTabRef获取的myTabRef这个组件,可以使用myTabRef上的方法。如图:

vm.$el:指明 Vue 实例的挂载目标。如this.$refs.myTabRef.$el获取的就是该标签的类名my-tab。如图:

总结:如果想要获取offsetWidth这个属性,不能直接用$refs,因为组件不是DOM元素,没有offsetWidth属性。需要通过$el来获取组件中的DOM元素。写法如下:

this.$refs.myTabRef.$el.offsetWidth;  //获取组件上DOM元素的offsetWidth
Logo

前往低代码交流专区

更多推荐