This commit is contained in:
张成
2025-08-25 15:57:54 +08:00
parent 1ad48b234c
commit 3ed48736b6
19 changed files with 4233 additions and 2097 deletions

250
src/static/scroll_helper.js Normal file
View File

@@ -0,0 +1,250 @@
/**
* 滚动控制助手 - 处理页面刷新和路由切换时的滚动行为
*/
class ScrollHelper {
constructor() {
this.isInitialized = false;
this.init();
}
/**
* 初始化滚动助手
*/
init() {
if (this.isInitialized) return;
// 监听页面加载完成事件
this.handlePageLoad();
// 监听路由变化事件
this.handleRouteChange();
// 监听页面刷新事件
this.handlePageRefresh();
// 监听浏览器前进后退事件
this.handleBrowserNavigation();
this.isInitialized = true;
}
/**
* 处理页面加载完成
*/
handlePageLoad() {
// 页面完全加载后滚动到顶部
if (document.readyState === 'complete') {
this.scrollToTop();
} else {
window.addEventListener('load', () => {
this.scrollToTop();
});
}
// DOM内容加载完成后也滚动到顶部
document.addEventListener('DOMContentLoaded', () => {
this.scrollToTop();
});
}
/**
* 处理路由变化
*/
handleRouteChange() {
// 监听 Vue Router 的全局前置守卫
if (window.Vue && window.Vue.prototype.$router) {
window.Vue.prototype.$router.beforeEach((to, from, next) => {
// 路由切换时滚动到顶部
this.scrollToTop();
next();
});
}
}
/**
* 处理页面刷新
*/
handlePageRefresh() {
// 监听页面即将刷新事件
window.addEventListener('beforeunload', () => {
// 保存当前滚动位置到 sessionStorage
sessionStorage.setItem('scrollPosition', window.pageYOffset);
});
// 页面加载完成后检查是否需要滚动到顶部
window.addEventListener('load', () => {
const savedPosition = sessionStorage.getItem('scrollPosition');
if (savedPosition) {
// 清除保存的位置
sessionStorage.removeItem('scrollPosition');
// 滚动到顶部
this.scrollToTop();
}
});
}
/**
* 处理浏览器前进后退
*/
handleBrowserNavigation() {
// 监听 popstate 事件(浏览器前进后退)
window.addEventListener('popstate', () => {
// 延迟执行,确保路由更新完成
setTimeout(() => {
this.scrollToTop();
}, 100);
});
}
/**
* 滚动到页面顶部
*/
scrollToTop(options = {}) {
const defaultOptions = {
top: 0,
left: 0,
behavior: 'smooth'
};
const config = { ...defaultOptions, ...options };
// 检查浏览器是否支持平滑滚动
if (!this.supportsSmoothScrolling()) {
config.behavior = 'auto';
}
// 执行滚动
window.scrollTo(config);
// 同时滚动 body 和 html 元素(兼容性处理)
if (document.body) {
document.body.scrollTop = 0;
document.body.scrollLeft = 0;
}
if (document.documentElement) {
document.documentElement.scrollTop = 0;
document.documentElement.scrollLeft = 0;
}
}
/**
* 滚动到指定元素
*/
scrollToElement(selector, options = {}) {
const element = document.querySelector(selector);
if (!element) return;
const defaultOptions = {
behavior: 'smooth',
block: 'start',
inline: 'nearest'
};
const config = { ...defaultOptions, ...options };
// 检查浏览器是否支持 scrollIntoView
if (element.scrollIntoView) {
element.scrollIntoView(config);
} else {
// 降级处理:计算元素位置并滚动
const rect = element.getBoundingClientRect();
const scrollTop = window.pageYOffset + rect.top;
this.scrollToTop({ top: scrollTop, behavior: config.behavior });
}
}
/**
* 检查浏览器是否支持平滑滚动
*/
supportsSmoothScrolling() {
return 'scrollBehavior' in document.documentElement.style;
}
/**
* 获取当前滚动位置
*/
getScrollPosition() {
return {
x: window.pageXOffset || document.documentElement.scrollLeft,
y: window.pageYOffset || document.documentElement.scrollTop
};
}
/**
* 设置滚动位置
*/
setScrollPosition(x, y, behavior = 'smooth') {
const options = {
top: y,
left: x,
behavior: this.supportsSmoothScrolling() ? behavior : 'auto'
};
window.scrollTo(options);
}
/**
* 滚动到底部
*/
scrollToBottom(behavior = 'smooth') {
const scrollHeight = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.body.clientHeight,
document.documentElement.clientHeight
);
this.scrollToTop({
top: scrollHeight,
behavior: behavior
});
}
/**
* 滚动到指定百分比位置
*/
scrollToPercentage(percentage, behavior = 'smooth') {
const scrollHeight = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight
);
const targetPosition = (scrollHeight - window.innerHeight) * (percentage / 100);
this.scrollToTop({
top: targetPosition,
behavior: behavior
});
}
/**
* 监听滚动事件
*/
onScroll(callback) {
window.addEventListener('scroll', callback, { passive: true });
}
/**
* 移除滚动监听器
*/
offScroll(callback) {
window.removeEventListener('scroll', callback);
}
/**
* 销毁滚动助手
*/
destroy() {
// 清理事件监听器
this.isInitialized = false;
}
}
// 创建全局实例
window.scrollHelper = new ScrollHelper();
// 导出类(如果使用模块系统)
if (typeof module !== 'undefined' && module.exports) {
module.exports = ScrollHelper;
}