vue3中使用锚点
html代码
<div class="cashierWrap"> <div class="projectNameNew"> <el-input class="projectNameSearch" v-model="keyword" placeholder="搜索项目名称/价格" maxlength="10" :prefix-icon="Search" clearable @input="searchPro" /> <div class="projectNameList"> <div class="projectNameListLeft"> <div :class="['projectNameListLeftTit', 'ellipsis', active == k ? 'activeTit' : '']" v-for="(v, k) in priceListData" :key="k" @click="HandlerItemGroupName(v, k)"><span v-if="active == k" class="spanLine"></span> {{ v.itemGroupName }}</div> </div> <div class="projectNameListRight" id="scrollContainer"> <div class="itemInfoList" :id="`itemInfoList${i}`" v-for="(v, i) in priceListData" :key="i"> <p class="itemName"> {{ v.itemGroupName }} </p> <div class="itemInfoWrap" v-if="v.shopItemList.length"> <div class="itemInfo" v-for="(v1, i1) in v.shopItemList" :key="i" @click="chooseProject(i, i1)"> <div class="proImg"> <img :src="v1.itemUrl" /> <img v-if="v1.choose" class="select" :src="proChoose" /> </div> <div class="proText"> <p class="ellipsis">{{ v1.shopItemName }}</p> <p class="mt0">¥{{ v1.shopItemPrice }}</p> </div> </div> </div> <div v-else class="itemInfoEmpty"> <div class="proImg"> <img class="select" :src="zanwu" /> </div> <div class="proText">暂无-</div> </div> </div> </div> </div> </div>
setup代码:
const chooseProjectArr = reactive({
active:1
})
const isScroll = ref(true); // 点击导航栏时,暂时停止监听页面滚动
//导航锚点
const HandlerItemGroupName = (item: any, index: any) => {
chooseProjectArr.active = index;
let anchor: any = document.querySelector(`#itemInfoList${index}`);
let scrollBox: any = document.getElementById("scrollContainer");
nextTick(() => {
scrollBox.scrollTo({
top: anchor.offsetTop - 11,
behavior: "smooth",
});
});
isScroll.value = false;
let timeId:any = "";
clearTimeout(timeId);
timeId = setTimeout(() => {
isScroll.value = true;
}, 2000);
};
// 滚动监听器
const onScroll = () => {
if (!isScroll.value) return;
// 获取所有锚点元素
const navContents = document.querySelectorAll(".projectNameListRight .itemInfoList");
// 所有锚点元素的 offsetTop
const offsetTopArr: any = [];
navContents.forEach((item:any) => {
offsetTopArr.push(item.offsetTop - 11);
});
// 获取当前文档流的 scrollTop
const scrollTop = document.getElementById("scrollContainer").scrollTop;
// 定义当前点亮的导航下标
let navIndex = 0;
for (let n = 0; n <= offsetTopArr.length; n++) {
// 如果 scrollTop 大于等于第 n 个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
// 那么此时导航索引就应该是 n 了
if (scrollTop >= offsetTopArr[n - 1]) {
navIndex = n - 1;
}
}
// 把下标赋值给 vue 的 data
chooseProjectArr.active = navIndex;
};
// 组件加载后监听指定div的滚动事件(scrollContainer)
onMounted(() => {
nextTick(() => {
document.getElementById("scrollContainer").addEventListener("scroll", onScroll);
});
});
//卸载监听
onBeforeUnmount(() => {
document.getElementById("scrollContainer").removeEventListener("scroll", onScroll);
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~