我的应用程序不使用文档/主体作为滚动主体,它使用带有 id
#overflow
的自定义 div 作为每个页面的主要滚动元素。这样做的原因是为了利用 3D 变换来实现视差和各种其他过渡功能,但我不会详细介绍。 所以请接受我的用例不需要在根上使用溢出。
因为我没有使用根作为我的滚动元素,所以默认路由器滚动链接到哈希 URL——比如
/some-page#some-hash
不起作用。因此,我需要覆盖默认的滚动行为,以便捕获页面上具有匹配 ID 的元素的任何哈希 URL 并适当地滚动到。但是,我似乎无法正常工作。我尝试了多种不同的方法:
在插件中使用 page:finish 钩子:
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('page:finish', () => {
const overflow = document.getElementById("overflow");
const hash = window.location.hash;
if (overflow) {
if (hash) {
const section = document.getElementById(hash.replace('#',''));
const distance = section ? section.getBoundingClientRect().top + window.scrollY - 120 : null;
overflow.scrollTo({top: distance, behavior: 'smooth'});
} else {
overflow.scrollTo(0, 0);
}
} else {
window.scrollTo(0, 0);
}
})
})
覆盖 scrollBehavior 并等待在插件的异步函数中在页面上找到元素:
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.$router.options.scrollBehavior = async (to, from, savedPosition) => {
if (savedPosition) {
return savedPosition;
}
const findEl = async (hash, x = 0) => {
return (
document.querySelector(hash) ||
new Promise((resolve) => {
if (x > 0) {
return resolve(document.querySelector("#overflow"));
}
setTimeout(() => {
resolve(findEl(hash, 1));
}, 100);
})
);
};
const overflow = await document.getElementById("overflow");
if (overflow) {
if (to.hash) {
const el = await findEl(to.hash);
//const distance = el ? el.getBoundingClientRect().top + window.scrollY - 120 : null;
const distance = el ? el.getBoundingClientRect().top - 120 : null;
console.log(distance);
if ("scrollBehavior" in overflow.style) {
return el.scrollTo({ top: 400, behavior: "smooth" }); // everything above works but just doesn't action the final scroll function
}
}
}
};
});
在 nuxt.config 的全局页面转换中使用 onAfterEnter 事件:
export default defineNuxtConfig({
app: {
pageTransition: {
name: 'page',
mode: 'out-in',
onAfterEnter: () => {
const hash = window.location.hash;
if (hash) {
const section = document.getElementById(hash.replace('#',''));
const overflow = document.getElementById('overflow');
const distance = section ? section.getBoundingClientRect().top + window.scrollY - 120 : null;
if (section && distance) {
overflow.scrollTo({top: distance, behavior: 'smooth'});
}
}
}
//duration:{ enter: 1000, leave: 800 }
},
}
});
在页面转换完成后呈现的页面组件上的挂载钩子中。
onMounted(() => {
const overflow = document.getElementById("overflow");
const hash = window.location.hash;
if (overflow) {
if (hash) {
const section = document.getElementById(hash.replace('#',''));
const distance = section ? section.getBoundingClientRect().top + window.scrollY - 120 : null;
overflow.scrollTo({top: distance, behavior: 'smooth'});
} else {
overflow.scrollTo(0, 0);
}
} else {
window.scrollTo(0, 0);
}
})
以上尝试均无效。有人有替代解决方案吗?