这是封装的组件 判断容器的滚动
接收父组件传来的Tab参数
<template>
<div class="tab-container">
<div class="tab-item" v-for="(item, index) in tabList" :key="index" :class="{ active: index === active }" @click="toggleTab(index)">
<img class="icon" :src="index === active ? item.icon_active : item.icon" alt="" />
{{ item.name }}
</div>
</div>
</template>
<script>
export default {
props: {
tabList: {
type: Array,
default: () => [],
},
},
data() {
return {
active: 0,
offsetLeft: 0,
timer: null,
};
},
watch: {
// active(newVal) {
// this.toggleTab(newVal);
// },
offsetLeft: {
handler(newVal) {
const container = document.querySelector(".tab-container");
container.scrollLeft = this.offsetLeft;
},
},
},
created() {},
mounted() {
// 监听滚动事件
window.addEventListener("scroll", this.onScroll, false);
},
destroy() {
// 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
window.removeEventListener("scroll", this.onScroll);
},
methods: {
// 滚动监听器
onScroll() {
const activeTab = document.querySelector(".tab-item.active");
this.offsetLeft = activeTab.offsetLeft;
const navContents = document.querySelectorAll(".row");
const offsetTopArr = [];
navContents.forEach((item) => {
offsetTopArr.push(item.offsetTop);
});
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
let navIndex = 0;
for (let n = 0; n < offsetTopArr.length; n++) {
if (scrollTop >= offsetTopArr[n]) {
navIndex = n;
}
}
if (scrollTop + document.documentElement.clientHeight === document.documentElement.scrollHeight) {
navIndex = offsetTopArr.length - 1;
setTimeout(() => {
const activeTab = document.querySelector(".tab-item.active");
const container = document.querySelector(".tab-container");
container.scrollLeft = activeTab.offsetLeft;
}, 10);
}
this.active = navIndex;
},
toggleTab(index) {
window.removeEventListener("scroll", this.onScroll);
this.active = index;
this.$nextTick(() => {
const activeTab = document.querySelector(".tab-item.active");
const container = document.querySelector(".tab-container");
container.scrollLeft = activeTab.offsetLeft;
});
let jump = document.querySelectorAll(".row");
let total = jump[index].offsetTop;
let distance = document.documentElement.scrollTop || document.body.scrollTop;
// 平滑滚动,时长500ms,每10ms一跳,共50跳
let that = this;
let step = total / 50;
if (total > distance) {
smoothDown();
} else {
let newTotal = distance - total;
step = newTotal / 50;
smoothUp();
}
function smoothDown() {
if (distance < total) {
distance += step;
document.body.scrollTop = distance;
document.documentElement.scrollTop = distance;
setTimeout(smoothDown, 10);
} else {
document.body.scrollTop = total;
document.documentElement.scrollTop = total;
window.addEventListener("scroll", that.onScroll, false);
}
}
function smoothUp() {
if (distance > total) {
distance -= step;
document.body.scrollTop = distance;
document.documentElement.scrollTop = distance;
setTimeout(smoothUp, 10);
} else {
document.body.scrollTop = total;
document.documentElement.scrollTop = total;
window.addEventListener("scroll", that.onScroll, false);
}
}
},
},
};
</script>
<style lang="scss" scoped>
.tab-container {
width: 100%;
height: 17.067vw;
border-radius: 2.667vw 2.667vw 0 0;
background: #fff;
overflow-y: auto;
display: -webkit-box;
-webkit-overflow-scrolling: touch;
box-shadow: 0px 2px 9px 0px RGB(129 128 128 / 50%);
scroll-behavior: smooth;
}
.tab-container::-webkit-scrollbar {
display: none;
}
.tab-item {
display: flex;
align-items: center;
position: relative;
padding: 0px 30px;
text-align: center;
color: #999;
font-size: 3.733vw;
letter-spacing: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.icon {
width: 3.733vw;
height: 3.733vw;
margin-right: 1.333vw;
}
}
.tab-item.active {
color: #0084ff;
}
</style>