uniapp 小程序可用 vue3

1.png

2.png
上代码
子组件:
<!-- tab -->
<template>
<view class="tab">
<view style="padding: 0 24rpx;">
<view class="v-tabs ">
<view
v-for="(item, index) in tabList"
:key="index"
class="custom-tab"
:class="activeTab === index?`active active${index}`: `active${index}`"
@click="changeTab($event,index)"
>{{ item }}</view>
<view class="underline" :style="{ transform: 'translateX(' + underlineTranslateX + 'px)' }"></view>
</view>
</view>
<swiper
class="swiper"
:circular="false"
:indicator-dots="false"
:autoplay="false"
@change="change"
@transition="transition"
:current="activeTab"
:duration="200"
>
<swiper-item v-for="(item, index) in tabList" :item-id="index" :key="index">
<slot :name="item"></slot>
</swiper-item>
</swiper>
</view>
</template>
<script setup>
import { defineProps, nextTick } from "vue";
const props = defineProps({
list: {
type: Array
}
});
const activeTab = ref(0);
const tabList = ref(props.list);
const underlineTranslateX = ref(0);
const widthList = ref([]);
const screenWidth = ref(0);
onMounted(async () => {
//储存宽度
const instance = getCurrentInstance();
const query = uni.createSelectorQuery().in(instance);
for (let i = 0; i < tabList.value.length; i++) {
const data = await new Promise(resolve => {
query
.select(`.active${i}`)
.boundingClientRect(resolve)
.exec();
});
widthList.value.push(data.width);
underlineTranslateX.value = widthList.value[0] / 2 - 8; //这里的8是下划线宽度的一半
startX.value = JSON.parse(JSON.stringify(underlineTranslateX.value))
}
screenWidth.value = uni.getSystemInfoSync().windowWidth;
});
// 滑块位置
const changeTab = (event, index) => {
activeTab.value = index;
let width = 0;
for (let i = 0; i <= index; i++) {
width += widthList.value[i];
}
width -= widthList.value[index] / 2; //这里是tab宽度减去自身的1/2
width += 32 * index - 8;
underlineTranslateX.value = width;
startX.value = JSON.parse(JSON.stringify(underlineTranslateX.value))
//changeTab改变时 取消页面滑动改变
transitionB.value = false;
setTimeout(()=>{
transitionB.value = true;
},300)
};
//翻页
const change = e => {
if (e.detail) {
changeTab("", e.detail.current);
}
};
//滑块随着页面翻动而移动
const startX = ref(0); // 触摸开始时的 X 坐标
const transitionB = ref(true); // 触摸开始时的 X 坐标
const transition = e => {
if (e.detail.dx < 0 && activeTab.value != 0&&transitionB.value) {//避免第一个翻页
//滚动长度是margin的一般 自身的一半以及 滚动的下一个目标的一半
underlineTranslateX.value=(startX.value+((e.detail.dx/screenWidth.value)*(32+((widthList.value[activeTab.value])/2)+((widthList.value[activeTab.value-1])/2))))
} else if (e.detail.dx > 0 && activeTab.value != tabList.value.length - 1&&transitionB.value) {
//滚动长度是margin的一般 自身的一半以及 滚动的下一个目标的一半 右滑是加1
underlineTranslateX.value=(startX.value+((e.detail.dx/screenWidth.value)*(32+((widthList.value[activeTab.value])/2)+((widthList.value[activeTab.value+1])/2))))
//向右滑动
}
};
</script>
<style lang='scss' scoped>
.v-tabs {
display: flex;
align-items: center;
position: relative;
.custom-tab {
font-size: 32rpx;
color: #969ba0;
margin-right: 64rpx;
padding: 0 2rpx; //保持放大缩小都一样
}
.active {
font-family: $psm;
font-size: 36rpx;
color: #171b1e;
line-height: 54rpx;
padding: 0; //保持放大缩小都一样
}
.underline {
width: 32rpx;
height: 8rpx;
background: #0078e6;
border-radius: 8rpx 8rpx 8rpx 8rpx;
position: absolute;
bottom: -8rpx;
left: 0;
transition: width 0.3s, transform 0.3s;
}
}
.tab{
height: 100%;
}
::v-deep .swiper {
// height: 150px;
height: 100%;
}
</style>
父组件
<!-- 记录 -->
<template>
<!-- <topbar :title="'记录'" /> -->
<view :style="{paddingTop: aqTop,height:height}">
<myTab class="myTab" :list="list" >
<!-- slot与name对应 具名插槽 -->
<view slot="a">
11111111
</view>
<view slot="b">22222222222222</view>
<view slot="c">33333333333333</view>
</myTab>
</view>
<tabbar :value="2" />
</template>
<script setup>
import tabbar from "@/components/tabbar/tabbar.vue";
import myTab from "@/components/myTab/myTab.vue";
import search from "@/components/search/search.vue";
// 安全区域顶部高度
const aqTop = uni.$u.sys().safeArea.top + "px";
const height = `calc(100% - ${aqTop})`
const list = ['a','b','c',]
const current = ref(0)
const change = (e) =>{
console.log(e.detail);
if(e.detail){
changeIndex(e.detail.current)
}
}
const changeIndex = (index) =>{
current.value = index
}
</script>
<style lang='scss' scoped>
.myTab{
}
</style>
