Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
mlaj
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2025-12-28 00:34:17 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
dc900c1332fc8969c88b06941c82dc0fb28106bf
dc900c13
1 parent
327c48d5
fix(StudyCoursePage): 修复滚动容器引用和滚动事件处理问题
修复滚动容器引用未正确初始化的bug 将全局滚动事件改为容器内滚动事件 优化标签切换时的滚动行为
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
42 additions
and
35 deletions
src/views/profile/StudyCoursePage.vue
src/views/profile/StudyCoursePage.vue
View file @
dc900c1
...
...
@@ -48,7 +48,7 @@
</div>
<!-- 滚动区域:详情、目录和互动内容 -->
<div class="overflow-y-auto flex-1"
<div
ref="scroll_container_ref"
class="overflow-y-auto flex-1"
:style="{ paddingTop: topWrapperHeight, height: 'calc(100vh - ' + topWrapperHeight + ')' }">
<!-- 详情区域 -->
<div id="detail" class="py-4 px-4">
...
...
@@ -195,6 +195,9 @@ const currentTabIndex = computed(() => {
const tabs_container_ref = ref(null);
const tabs_container_width = ref(0);
const tabs_resize_observer = ref(null);
const scroll_container_ref = ref(null);
const scroll_container_el = ref(null);
const is_tab_scrolling = ref(false);
/**
* 初始化并监听标签容器宽度
...
...
@@ -325,8 +328,12 @@ onMounted(async () => {
/**
* 初始化时计算topWrapperHeight
*/
// 添加滚动监听
window.addEventListener('scroll', handleScroll);
nextTick(() => {
if (scroll_container_ref.value) {
scroll_container_el.value = scroll_container_ref.value;
scroll_container_el.value.addEventListener('scroll', handleScroll, { passive: true });
}
});
// 添加窗口大小变化监听
window.addEventListener('resize', updateTopWrapperHeight);
// 确保在组件挂载后计算高度
...
...
@@ -337,7 +344,10 @@ onMounted(async () => {
// 在组件卸载时移除监听器
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll);
if (scroll_container_el.value) {
scroll_container_el.value.removeEventListener('scroll', handleScroll);
scroll_container_el.value = null;
}
window.removeEventListener('resize', updateTopWrapperHeight);
// 组件卸载时取消监听
if (resizeObserver.value) {
...
...
@@ -354,19 +364,14 @@ onUnmounted(() => {
// 处理滚动事件
// 在script setup中添加
const isTabFixed = ref(false);
const tabOriginalTop = ref(0);
onMounted(async () => {
setTimeout(() => {
nextTick(() => {
// 记录标签页原始位置
const tabElement = document.querySelector('.py-3.bg-white');
if (tabElement) {
tabOriginalTop.value = tabElement.getBoundingClientRect().top + window.scrollY;
}
})
}, 500);
});
const get_container_relative_top = (el) => {
const container = scroll_container_ref.value;
if (!container || !el) return 0;
const container_rect = container.getBoundingClientRect();
const el_rect = el.getBoundingClientRect();
return el_rect.top - container_rect.top + container.scrollTop;
};
// 防抖函数
const debounce = (fn, delay) => {
...
...
@@ -385,27 +390,27 @@ const debounce = (fn, delay) => {
* 注释:当互动区域不存在时,仅在详情与目录之间联动
*/
const handleScroll = debounce(() => {
if (is_tab_scrolling.value) return;
const detailElement = document.getElementById('detail');
const catalogElement = document.getElementById('catalog');
const interactionElement = document.getElementById('interaction');
const
tabElement = document.querySelector('.py-3.bg-white')
;
if (!detailElement || !catalogElement || !
tabElement
) return;
const
container = scroll_container_ref.value
;
if (!detailElement || !catalogElement || !
container
) return;
const currentScrollY = window.scrollY;
isTabFixed.value = currentScrollY >= tabOriginalTop.value;
isTabFixed.value = false;
const scrollTop = window.scrollY;
const tabHeight = tabElement.offsetHeight;
const buffer = 50; // 缓冲区域
const scrollTop = container.scrollTop;
const buffer = 20; // 缓冲区域
// 计算各区域顶部位置(互动不存在则设为无穷大)
const detailTop =
detailElement.offsetTop - tabHeight
- buffer;
const catalogTop =
catalogElement.offsetTop - tabHeight
- buffer;
const interactionTop = interactionElement ? (
interactionElement.offsetTop - tabHeight
- buffer) : Infinity;
const detailTop =
get_container_relative_top(detailElement)
- buffer;
const catalogTop =
get_container_relative_top(catalogElement)
- buffer;
const interactionTop = interactionElement ? (
get_container_relative_top(interactionElement)
- buffer) : Infinity;
// 页面高度与底部判断
const scrollHeight =
document.documentElement
.scrollHeight;
const clientHeight =
document.documentElement
.clientHeight;
const scrollHeight =
container
.scrollHeight;
const clientHeight =
container
.clientHeight;
const isAtBottom = scrollTop + clientHeight >= scrollHeight - buffer;
// 联动判断
...
...
@@ -434,15 +439,17 @@ const getTransitionTiming = (current, previous) => {
const handleTabChange = (name) => {
previousTab.value = activeTab.value;
activeTab.value = name; // 立即更新activeTab的值
let offset = 100; // 调整偏移量, 配合目录的高度
is_tab_scrolling.value = true;
nextTick(() => {
const element = document.getElementById(name);
if (element) {
const topOffset = element.offsetTop - offset - parseInt(topWrapperHeight.value);
window.scrollTo({
top: topOffset,
behavior: 'smooth'
});
if (element && scroll_container_ref.value) {
const topOffset = Math.max(0, get_container_relative_top(element) - 10);
scroll_container_ref.value.scrollTo({ top: topOffset, behavior: 'smooth' });
setTimeout(() => {
is_tab_scrolling.value = false;
}, 500);
} else {
is_tab_scrolling.value = false;
}
});
};
...
...
Please
register
or
login
to post a comment