实现效果:跨页面跳转后定位到页面相应位置,这个需求常在官网底部导航栏开发中遇到
vue3+ts开发官网底部导航为例,我的底部导航封装为了一个组件,所以会涉及到父子组件传参,不清楚的伙伴可以去查一下相关资料
注意:这里的跨页面锚点定位分为从一个页面跳转到另一个页面后锚点定位和当前页面锚点定位(点击底部导航内当前页面的导航实现锚点定位)
子组件Footer.vue
//标签 <ul> <li>关于我们</li> <li @click="pageSkip('/AboutUs', 'aboutUs_introduce')">公司简介</li> <li @click="pageSkip('/AboutUs', 'aboutUs_culture')">企业文化</li> <li @click="pageSkip('/AboutUs', 'aboutUs_idea')">经营理念</li> </ul> import { useRouter, useRoute } from "vue-router" const router = useRouter() const route = useRoute() const emit = defineEmits(['anchorSkip'])//引入父组件中定义的方法,用于当前页面锚点定位 let anchor = reactive({ value: '' })//页面跳转后传递的参数,要写为对象形式,不然参数穿过去后会变成一个一个的字符 const pageSkip = (val1, val2?) => {//第一个参数是路由地址,第二个参数是跳转后锚点定位的位置,第二个参数后面的?是因为其他页面跳转也用的这个方法,但是不用传参数所以用?表示该参数可有可无(ts) if (route.path == val1) {//通过路由判断是当前页面使用锚点定位还是跨页面使用锚点定位 emit('anchorSkip', val2) } else { anchor.value = val2 router.push({ path: val1, query: anchor }) } }
复制
父组件AboutUs.vue
//HTML <template> <div id="scroll_top"> <div id="aboutUs_culture"></div>//页面需要定位到的位置,使用id命名 <div id="aboutUs_culture"></div> <div id="aboutUs_culture"></div> <Footer @anchorSkip="anchorSkip"></Footer>//引入子组件标签,自定义事件 </div> </template> //js //其他页面跳转过来的锚点定位 onMounted(() => {//在onMounted钩子中判断是不是从底部导航跳转过来的 if (route.query && route.query.value) {//底部导航跳转过来的则定位到响应位置 document.querySelector('#' + `${route.query.value}`).scrollIntoView(); } else {//其他位置跳转过来不需要定位的则定位到顶部 document.querySelector('#scroll_top').scrollIntoView() } }) //当前页面使用锚点定位 const anchorSkip = (val) => {//Footer.vue触发该事件 document.querySelector('#' + val).scrollIntoView(); }
复制
这样就OK了
最开始的时候我用的是其他方法:
1.监听路由变化:这种方法可以实现页面跳转后锚点定位,但却无法实现本页面内锚点定位,因为路由没有变化
2.定义一个变量,监听该变量:由于监听路由没有实现本页面锚点定位,所以我想了这个方法,其实和监听路由差不多,但是最后还是没有实现本页面锚点定位
3.父组件中监听路由或使用updateed钩子:这种方法实现了当前页面锚点定位,但是如果在当前页面内多次点击同一个导航的话不会触发锚点定位,因为这种方法相当于监听路由变化,而在同一个页面中多次点击同一个导航路由(及传的参数)是没有变化的,所以不会触发锚点定位,且从其他不需要锚点定位页面跳转过来后页面会报scrollIntoView()方法错误。
以上1、2方法都没有实现当前页面锚点定位,原因我也还在查资料,知道答案的伙伴可以在评论区分享一手,我查阅到资料后也会及时更新的。