效果演示
代码:
<script lang="ts" setup> /** 使用 ref 管理锚点元素 */ const abTcomptionRef = ref<HTMLElement | null>(null); const openClassessRef = ref<HTMLElement | null>(null); const contestPrivilegesRef = ref<HTMLElement | null>(null); const competitionExamplesRef = ref<HTMLElement | null>(null); const conDynamicsRef = ref<HTMLElement | null>(null);const titleList = reactive([{ name: 'first', path: 'abTcomption' },{ name: 'second', path: 'openClassess' },{ name: 'three', path: 'contestPrivileges' },{ name: 'four', path: 'competitionExamples' },{ name: 'five', path: 'conDynamics' } ]) const anchorRefs = {abTcomption: abTcomptionRef,openClassess: openClassessRef,contestPrivileges: contestPrivilegesRef,competitionExamples: competitionExamplesRef,conDynamics: conDynamicsRef }; const elementList = reactive([{name: 'first',ref: 'abTcomptionRef',path: 'abTcomption',component: shallowRef(aboutTheCompetition),color: '#252635'// show: Number(props.type) === 1,},{name: 'second',ref: 'openClassessRef',path: 'openClassess',component: shallowRef(openClasses),color: '#0A0B15',showMore: true,pageMore: false},{name: 'three',ref: 'contestPrivilegesRef',path: 'contestPrivileges',component: shallowRef(contestPrivileges),color: '#252635'},{name: 'four',ref: 'competitionExamplesRef',path: 'competitionExamples',component: shallowRef(competitionExamples),color: '#0A0B15',showMore: true,pageMore: false},{name: 'five',ref: 'conDynamicsRef',path: 'conDynamics',component: shallowRef(contestDynamics),color: '#252635',showMore: true,pageMore: false} ])/** 跳转到锚点位置 */ const anchorPosition = (anchor: string) => {const ref2 = anchorRefs[anchor];console.log('ref');console.log(ref2);if (ref2 instanceof Array) {ref2[0].scrollIntoView({ behavior: 'smooth' });//设置滚动到实例位置} else if (Object.prototype.toString.call(ref2).indexOf('HTMLDivElement') > -1) {ref2.scrollIntoView({ behavior: 'smooth' });} else {console.warn(`未找到锚点元素: ${anchor}`);} }; </script>
<template><div class="flex gap-10 my-20px w-[70%] m-auto"><template v-for="(item, index) in titleList" :key="index"><div class="tag" :class="{ active: item.path === currentPath }" @click="anchorPosition(item.path)">{{ item.name }}</div></template></div><div :ref="(el) => { anchorRefs[item.path] = el }"v-for="(item, index2) in elementList":style="{ backgroundColor: item.color }":class="['pt-[6px]', !item.showMore||dataList[item.ref]?.length <=3 ? 'pb-[80px]' : 'pb-[40px]']":key="index2"><div class="container-title">{{ item.name }}</div><div class="w-[70%] m-auto"><component :is="item.component" :dataContent="dataList[item.ref]" /></div></div> </template>
知识点一:
使用shallowRef可以实现浅层响应式引用组件实例,当对象的深层属性发生变化时不会触发视图更新,提高了性能
知识点二:
由于引用组件实例,组件未挂载完成就获取ref,会出现此ref还未完全获取到组件撑开区域的高度,就会出现锚点滚动定位位置错乱的问题,修改ref写法,(el)=> {anchorRefs[item.path] = el }