uniapp 导航栏 手写组件



<template>
    <view class="nav-bar-nav-bar">
        <scroll-view scroll-x="true" class="nav-bar-scroll-view" show-scrollbar="false">
            <view class="nav-bar-nav-item"  :style="{ padding: '0 ' + text_padding + 'rpx' }" v-for="(item, index) in navItems" :key="index" @tap="selectItem(index)">
                <text :class="['nav-bar-nav-text', { 'nav-bar-active': currentIndex === index }]"
                    :style="{ fontSize: fontSize + 'rpx' }">{
   
   { item }}</text>
                <view :class="['nav-bar-indicator', { 'nav-bar-active': currentIndex === index }]" :style="{
                    width: currentIndex === index ? indicatorWidth + 'rpx' : '0', height: dynamicHeight + 'rpx'
                }">
                </view>
            </view>
        </scroll-view>
    </view>
</template>

<script>
export default {
    name: 'NavBar',
    props: {
        text_padding: {  //字之间的间距
            type: [Number, String],
            default: 20
        },
        dynamicHeight: {  //active下滑高度
            type: [Number, String],
            default: 6
        },
        indicatorWidth: {  //active下滑宽度
            type: [Number, String],
            default: 40
        },
        fontSize: { //字体大小
            type: [Number, String],
            default: '28'
        },
        navItems: {
            type: Array,
            default: () => ['首页',]
        },
        defaultIndex: {
            type: Number,
            default: 0
        }
    },
    data() {
        return {
            currentIndex: this.defaultIndex
        }
    },
    methods: {
        selectItem(index) {
            this.currentIndex = index
            this.$emit('item-selected', index)
        }
    }
}
</script>

<style scoped>
.nav-bar-nav-bar {
    background-color: #ffffff;
    padding: 10rpx 0;
}

.nav-bar-scroll-view {
    white-space: nowrap;
}

.nav-bar-nav-item {
    display: inline-block;
    
    position: relative;
    text-align: center;
}

.nav-bar-nav-text {
    color: #333333;
    font-weight: bold;
    line-height: 60rpx;
}

.nav-bar-active {
    color: #68B95A;
    font-weight: bold;
    border-radius: 4rpx 4rpx 4rpx 4rpx;
}

.nav-bar-indicator {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 0;

    background-color: #68B95A;
    transition: width 0.3s;
}
</style>

使用组件

<template>
    <view>
        <NavBar :navItems="myNavItems" :fontSize="26" :dynamicHeight="4" :indicatorWidth="30" @item-selected="onItemSelected" />

        <view class="content-container">
            <view v-for="(content, index) in contentItems" :key="index"
                  class="content-page"
                  :class="{ 
                      'active': selectedIndex === index,
                      'left': index < selectedIndex,
                      'right': index > selectedIndex
                  }">
                <view v-for="(box, boxIndex) in content.boxes" :key="boxIndex" class="content-box">
                    {
   
   { box.title }}
                </view>
            </view>
        </view>
    </view>
</template>

<script>
import NavBar from './xztdemoNavBar.vue'

export default {
    components: {
        NavBar
    },
    data() {
        return {
            myNavItems: ['首页', '北京同仁堂', '正官庄', '仙芝楼', '江中', 'swisses', '品牌馆'],
            selectedIndex: 0,
            contentItems: [
                {
                    boxes: [
                        { title: '首页盒子1' },
                        { title: '首页盒子2' },
                        { title: '首页盒子3' }
                    ]
                },
                {
                    boxes: [
                        { title: '北京同仁堂盒子1' },
                        { title: '北京同仁堂盒子2' }
                    ]
                },
                {
                    boxes: [
                        { title: '正官庄盒子1' },
                        { title: '正官庄盒子2' },
                        { title: '正官庄盒子3' },
                        { title: '正官庄盒子4' }
                    ]
                },
                // 添加更多内容项...
            ]
        }
    },
    methods: {
        onItemSelected(index) {
            this.selectedIndex = index;
        }
    }
}
</script>

<style>
.content-container {
    position: relative;
    width: 100%;
    height: 600rpx; /* 根据内容调整高度 */
    overflow: hidden;
}

.content-page {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    transition: all 0.3s ease;
    opacity: 0;
    transform: translateX(100%);
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    align-content: flex-start;
}

.content-page.active {
    opacity: 1;
    transform: translateX(0);
}

.content-page.left {
    transform: translateX(-100%);
}

.content-page.right {
    transform: translateX(100%);
}

.content-box {
    width: 45%;
    height: 200rpx;
    margin: 10rpx;
    background-color: #f0f0f0;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 10rpx;
    font-size: 24rpx;
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_44759522/article/details/141157842
今日推荐