perf(StudyCoursePage): 优化滚动和标签页切换的性能
引入防抖函数减少滚动事件触发频率,优化handleScroll函数的逻辑,增加缓冲区域判断。同时,移除handleTabChange函数中的setTimeout,立即更新activeTab的值,提升用户体验。
Showing
1 changed file
with
43 additions
and
19 deletions
| ... | @@ -217,8 +217,19 @@ onMounted(async () => { | ... | @@ -217,8 +217,19 @@ onMounted(async () => { |
| 217 | }, 500); | 217 | }, 500); |
| 218 | }); | 218 | }); |
| 219 | 219 | ||
| 220 | +// 防抖函数 | ||
| 221 | +const debounce = (fn, delay) => { | ||
| 222 | + let timer = null; | ||
| 223 | + return function (...args) { | ||
| 224 | + if (timer) clearTimeout(timer); | ||
| 225 | + timer = setTimeout(() => { | ||
| 226 | + fn.apply(this, args); | ||
| 227 | + }, delay); | ||
| 228 | + }; | ||
| 229 | +}; | ||
| 230 | + | ||
| 220 | // 修改handleScroll函数 | 231 | // 修改handleScroll函数 |
| 221 | -const handleScroll = () => { | 232 | +const handleScroll = debounce(() => { |
| 222 | const detailElement = document.getElementById('detail'); | 233 | const detailElement = document.getElementById('detail'); |
| 223 | const catalogElement = document.getElementById('catalog'); | 234 | const catalogElement = document.getElementById('catalog'); |
| 224 | const interactionElement = document.getElementById('interaction'); | 235 | const interactionElement = document.getElementById('interaction'); |
| ... | @@ -229,17 +240,31 @@ const handleScroll = () => { | ... | @@ -229,17 +240,31 @@ const handleScroll = () => { |
| 229 | isTabFixed.value = currentScrollY >= tabOriginalTop.value; | 240 | isTabFixed.value = currentScrollY >= tabOriginalTop.value; |
| 230 | 241 | ||
| 231 | const scrollTop = window.scrollY; | 242 | const scrollTop = window.scrollY; |
| 232 | - const catalogOffset = catalogElement.offsetTop - (isTabFixed.value ? tabElement.offsetHeight : 0); | 243 | + const tabHeight = tabElement.offsetHeight; |
| 233 | - const interactionOffset = interactionElement.offsetTop - (isTabFixed.value ? tabElement.offsetHeight : 0); | 244 | + const buffer = 50; // 缓冲区域 |
| 245 | + | ||
| 246 | + // 计算每个区域的位置,考虑固定标签页的高度 | ||
| 247 | + const detailTop = detailElement.offsetTop - tabHeight - buffer; | ||
| 248 | + const catalogTop = catalogElement.offsetTop - tabHeight - buffer; | ||
| 249 | + const interactionTop = interactionElement.offsetTop - tabHeight - buffer; | ||
| 234 | 250 | ||
| 235 | - if (scrollTop >= interactionOffset) { | 251 | + // 获取页面总高度和视口高度 |
| 252 | + const scrollHeight = document.documentElement.scrollHeight; | ||
| 253 | + const clientHeight = document.documentElement.clientHeight; | ||
| 254 | + const isAtBottom = scrollTop + clientHeight >= scrollHeight - buffer; | ||
| 255 | + | ||
| 256 | + // 判断当前滚动位置所在区域 | ||
| 257 | + if (scrollTop <= detailTop) { | ||
| 258 | + activeTab.value = 'detail'; | ||
| 259 | + } else if (isAtBottom || scrollTop >= interactionTop) { | ||
| 236 | activeTab.value = 'interaction'; | 260 | activeTab.value = 'interaction'; |
| 237 | - } else if (scrollTop >= catalogOffset) { | 261 | + } else if (scrollTop >= catalogTop && scrollTop < interactionTop) { |
| 238 | activeTab.value = 'catalog'; | 262 | activeTab.value = 'catalog'; |
| 239 | - } else { | 263 | + } else if (scrollTop >= detailTop && scrollTop < catalogTop) { |
| 240 | activeTab.value = 'detail'; | 264 | activeTab.value = 'detail'; |
| 241 | } | 265 | } |
| 242 | -}; | 266 | +}, 100); |
| 267 | + | ||
| 243 | 268 | ||
| 244 | // 处理标签页切换 | 269 | // 处理标签页切换 |
| 245 | // 在script setup中添加 | 270 | // 在script setup中添加 |
| ... | @@ -253,19 +278,18 @@ const getTransitionTiming = (current, previous) => { | ... | @@ -253,19 +278,18 @@ const getTransitionTiming = (current, previous) => { |
| 253 | // 修改handleTabChange函数 | 278 | // 修改handleTabChange函数 |
| 254 | const handleTabChange = (name) => { | 279 | const handleTabChange = (name) => { |
| 255 | previousTab.value = activeTab.value; | 280 | previousTab.value = activeTab.value; |
| 281 | + activeTab.value = name; // 立即更新activeTab的值 | ||
| 256 | let offset = 100; // 调整偏移量, 配合目录的高度 | 282 | let offset = 100; // 调整偏移量, 配合目录的高度 |
| 257 | - setTimeout(() => { | 283 | + nextTick(() => { |
| 258 | - nextTick(() => { | 284 | + const element = document.getElementById(name); |
| 259 | - const element = document.getElementById(name); | 285 | + if (element) { |
| 260 | - if (element) { | 286 | + const topOffset = element.offsetTop - offset - parseInt(topWrapperHeight.value); |
| 261 | - const topOffset = element.offsetTop - offset - parseInt(topWrapperHeight.value); | 287 | + window.scrollTo({ |
| 262 | - window.scrollTo({ | 288 | + top: topOffset, |
| 263 | - top: topOffset, | 289 | + behavior: 'smooth' |
| 264 | - behavior: 'smooth' | 290 | + }); |
| 265 | - }); | 291 | + } |
| 266 | - } | 292 | + }); |
| 267 | - }); | ||
| 268 | - }, 100); | ||
| 269 | }; | 293 | }; |
| 270 | 294 | ||
| 271 | // 课程数据 | 295 | // 课程数据 | ... | ... |
-
Please register or login to post a comment