1
This commit is contained in:
250
src/static/scroll_helper.js
Normal file
250
src/static/scroll_helper.js
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user