- 普通方法
<!-- 1. 目标元素设置id -->
<section id="section1">内容区域</section>
<!-- 2. 锚点链接 -->
<a href="#section1">跳转到第一节</a>
<!-- 3. 或通过JavaScript -->
location.hash = '#section1';
启用平滑滚动
/* 启用全局平滑滚动 */
html {
scroll-behavior: smooth;
}
-
JS 实现
在单页面应用中,哈希滚动会与路由系统产生冲突,特别是当使用哈希路由模式时。
方案一
// 约定:路由哈希以 "/" 开头,锚点哈希以 "!" 开头
<a href="#!features">功能特性</a>
// 路由配置
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/!*', redirect: to => {
// 处理锚点跳转
const hash = to.path.replace('/!', '');
scrollToHash(`#${hash}`);
return { path: '/' }; // 保持在当前路由
}}
]
});
方案二:使用 query 参数代替 hash
// 使用 ?section=features 代替 #features
<a href="?section=features">功能特性</a>
// 路由处理
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/', component: Home, props: route => ({
section: route.query.section
})}
]
});
// 组件内监听
export default {
props: ['section'],
watch: {
section(newSection) {
if (newSection) {
this.$nextTick(() => {
const element = document.getElementById(newSection);
if (element) element.scrollIntoView({ behavior: 'smooth' });
});
}
}
}
};
方案三:Vue Router 官方方案
// Vue Router 4.x
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory(),
routes: [...],
// 处理哈希滚动
scrollBehavior(to) {
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth',
top: 100 // 为固定导航栏预留空间
};
}
}
});
// 在组件中使用
<template>
<!-- 使用 vue-router 的滚动功能 -->
<router-link :to="{ hash: '#section1' }">章节1</router-link>
</template>
方案四:React Router 解决方案
import { useNavigate, useLocation } from 'react-router-dom';
function AnchorLink({ to, children }) {
const navigate = useNavigate();
const location = useLocation();
const handleClick = (e) => {
e.preventDefault();
const [path, hash] = to.split('#');
if (location.pathname === path) {
// 同页面滚动
const element = document.getElementById(hash);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
// 更新URL
window.history.pushState(null, null, `#${hash}`);
}
} else {
// 跨页面导航
navigate(to);
}
};
return (
<a href={to} onClick={handleClick}>
{children}
</a>
);
}
// 在目标页面添加滚动效果
function Page() {
const location = useLocation();
useEffect(() => {
if (location.hash) {
const element = document.getElementById(location.hash.substring(1));
if (element) {
setTimeout(() => {
element.scrollIntoView({ behavior: 'smooth' });
}, 100);
}
}
}, [location]);
return <div>...</div>;
}
评论区