赞
踩
效果截图:
前言:
最近开发小程序,需要用到tabs组件,在标签多的时候,可以左右滑动。在插件库找到uView UI,但是这个库插件体积不算太小,小程序尽可能需要减少包体积,于是就打算自己封装一下。
主要能力:选中的tab会自动移动到组件的中间位置,支持默认选中第几个tab,可联动获取数据,支持和swiper联动使用。
主要方法:scroll-view
- scroll-x:true //允许横向滚动
-
- scroll-left //设置横向滚动条位置
-
- scroll-with-animation //在设置滚动条位置时使用动画过渡
tabs接受的参数props,tablist是父组件传递过来的tab数组,defaultsSelectIndex默认选中的第几个tab。
<tabs :tablist='list' :defaultSelectIndex='defaultSelectIndex' @select='change'></tabs>
计算每个tab的宽度
- onMounted(() => {
- const query = uni.createSelectorQuery().in(getCurrentInstance());
-
- query.selectAll('.tabs-scroll_item').boundingClientRect((data:Array<UniApp.NodeInfo>) => {
- let dataLen = data.length;
- for (let i = 0; i < dataLen; i++) {
- // scroll-view 子元素组件距离左边栏的距离
- itemList.value[i].left = data[i].left;
- // scroll-view 子元素组件宽度
- itemList.value[i].width = data[i].width
- }
- }).exec()
-
-
- })
select选中的tab暴露给父组件的方法。
- const emits=defineEmits<{
- (e : 'select',value : ItabItem) : void
- }>()
隐藏滑动条
- /* 隐藏滚动条*/
- ::v-deep.uni-scroll-view::-webkit-scrollbar {
- display: none
- }
组件实现代码tabs.vue
- <template>
- <view class="nav">
- <scroll-view class="tabs" scroll-x="true" scroll-with-animation :scroll-left="scrollLeft">
- <view class="tabs-scroll">
- <view class="tabs-scroll_item" v-for=" (item,index) in itemList" :key="index"
- :class="{'active':selectIndex==index}" @click="chenked(index)">
- {{item.title}}
- </view>
- </view>
- </scroll-view>
- </view>
- </template>
-
- <script setup lang="ts">
- import { getCurrentInstance, onMounted, ref, watch } from "vue";
- const scrollLeft = ref<number>(0)
- const selectIndex = ref<number>(0)
- const itemList = ref<Array<ItabItem>>()
- interface ItabItem {
- title : string
- width ?: number
- left ?: number
- id : number
- }
- interface Iprops {
- tablist : Array<ItabItem>
- defaultSelectIndex ?: number
- }
-
- const props = withDefaults(defineProps<Iprops>(), {
- tablist: () => [],
- defaultSelectIndex: 6
- })
- const emits=defineEmits<{
- (e : 'select',value : ItabItem) : void
- }>()
- const chenked = (index:number) => {
- selectIndex.value = index
- scrollLeft.value = 0
- for (let i = 0; i < index - 2; i++) {
- scrollLeft.value = scrollLeft.value + itemList.value[i]?.width
- }
- emits('select',props.tablist[index])
- }
- onMounted(() => {
- const query = uni.createSelectorQuery().in(getCurrentInstance());
-
- query.selectAll('.tabs-scroll_item').boundingClientRect((data:Array<UniApp.NodeInfo>) => {
- let dataLen = data.length;
- for (let i = 0; i < dataLen; i++) {
- // scroll-view 子元素组件距离左边栏的距离
- itemList.value[i].left = data[i].left;
- // scroll-view 子元素组件宽度
- itemList.value[i].width = data[i].width
- }
- }).exec()
-
-
- })
- watch(() => [props.tablist, props.defaultSelectIndex], () => {
- itemList.value = props.tablist
- selectIndex.value = props.defaultSelectIndex
- if(props.defaultSelectIndex!==0){
- setTimeout(()=>{
- chenked(props.defaultSelectIndex)
- },50)
- }
- }, {
- immediate: true
- })
- </script>
- <style lang="scss" scoped>
- .nav {
-
- background-color: rgba(0, 0, 0, .1);
- position: fixed;
- z-index: 99;
- width: 100%;
- align-items: center;
- height: 100rpx;
-
- .tabs {
- flex: 1;
- overflow: hidden;
- box-sizing: border-box;
- padding-left: 30rpx;
- padding-right: 30rpx;
-
- .tabs-scroll {
- display: flex;
- align-items: center;
- flex-wrap: nowrap;
- box-sizing: border-box;
-
- .tabs-scroll_item {
- line-height: 60rpx;
- margin-right: 35rpx;
- flex-shrink: 0;
- padding-bottom: 10px;
- display: flex;
- justify-content: center;
- font-size: 16px;
- padding-top: 10px;
- }
- }
- }
- }
-
-
- .active {
- position: relative;
- color: #333;
- font-weight: 800;
- }
-
- .active::after {
- content: "";
- position: absolute;
- width: 40rpx;
- height: 8rpx;
- border-radius: 8rpx;
- background-color: #333;
- left: 0px;
- right: 0px;
- bottom: 0px;
- margin: auto;
- }
-
- /* 隐藏滚动条,但依旧具备可以滚动的功能 */
- ::v-deep.uni-scroll-view::-webkit-scrollbar {
- display: none
- }
- </style>
使用方法index.vue
- <template>
- <view>
- <text style="text-align: center;width: 100%;display: block;"> 标题</text>
- <tabs :tablist='list' :defaultSelectIndex='defaultSelectIndex' @select='change'></tabs>
- </view>
- <button @click="add" style="margin-top: 100rpx;">父组件调用切换</button>
-
- </template>
-
- <script lang="ts" setup>
- import { ref } from "vue";
- const defaultSelectIndex=ref(0)
- const list = ref([
-
- {
- id: 1,
- title: '直播直播',
- },
- {
- id: 2,
- title: '热门推荐',
- },
- {
- id: 3,
- title: '音乐',
- },
- {
- id: 4,
- title: '经典小说',
- },
- {
- id: 5,
- title: '看书',
- },
- {
- id: 6,
- title: '短剧',
- },
- {
- id: 7,
- title: '相声评述',
- },
- {
- id: 8,
- title: '找书广场',
- },
- ])
- const change=(value)=>{
- uni.showToast({
- title: value.title,
- duration: 2000
- });
-
- }
- const add=( )=>{
- defaultSelectIndex.value++
- }
- </script>
-
- <style>
-
- </style>
希望本篇文章对你有所帮助,我也是根据自己的需求封装的,你也可以根据自己的需求在该代码上进行优化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。