Tauri文件查看器单轴滚动阻塞另一轴的问题排查
问题排查与解决方案
核心原因分析
- 滚动事件高频触发+异步请求堆积:每次滚动都会触发
lazy_redraw调用Rust后端,异步请求返回后更新DOM。快速滚动时,大量未完成的请求会集中更新DOM,抢占主线程资源,导致另一轴向滚动的事件处理被延迟。 - requestAnimationFrame滥用:之前的RAF写法会持续递归调用
scrollHandler,即使没有滚动操作也一直在运行,持续占用主线程,加剧滚动卡顿。 - 滚动事件绑定对象混淆:如果滚动事件绑定在
window上,而模拟滚动容器是自定义div,可能导致事件冒泡或冲突,两个轴向的滚动事件处理互相干扰。
具体解决方案
1. 给滚动事件加节流,控制请求频率
用节流函数限制lazy_redraw的触发频率,避免短时间内发送过多Rust请求:
let isThrottled = false; const THROTTLE_DELAY = 100; // 可根据性能调整 // 注意:绑定到你的模拟滚动容器而非window const scrollContainer = document.querySelector(".scroll-container"); scrollContainer.addEventListener("scroll", () => { if (isThrottled) return; isThrottled = true; setTimeout(() => { const currentLinesAbove = get_lines_above_viewport(); if (last_number_of_lines_above_viewport !== currentLinesAbove) { lazy_redraw(); last_number_of_lines_above_viewport = currentLinesAbove; } isThrottled = false; }, THROTTLE_DELAY); });
2. 修复requestAnimationFrame的使用(可选,配合节流)
确保滚动停止后停止RAF循环,避免无效执行:
let animationFrameId = null; let lastScrollTime = Date.now(); const scrollContainer = document.querySelector(".scroll-container"); scrollContainer.addEventListener("scroll", () => { lastScrollTime = Date.now(); if (!animationFrameId) { animationFrameId = requestAnimationFrame(scrollHandler); } }); function scrollHandler() { const currentLinesAbove = get_lines_above_viewport(); if (last_number_of_lines_above_viewport !== currentLinesAbove) { lazy_redraw(); last_number_of_lines_above_viewport = currentLinesAbove; } // 滚动停止100ms后停止RAF循环 if (Date.now() - lastScrollTime > 100) { cancelAnimationFrame(animationFrameId); animationFrameId = null; } else { animationFrameId = requestAnimationFrame(scrollHandler); } }
3. 处理异步请求的竞态问题
避免旧的请求结果覆盖新的,只处理最新请求的返回:
let currentRequestId = 0; function lazy_redraw() { if (!loaded_file) return; const requestId = ++currentRequestId; invoke('lazy_read_lines', { file_path: loaded_file.file_path, filter: filtered_tab_lines.slice(get_lines_above_viewport(), get_lines_above_viewport() + get_lines_inside_viewport()) }).then((message) => { // 仅处理最新请求的结果 if (requestId === currentRequestId) { document.querySelector(".file").innerText = message; } }); }
4. 优化元素的样式与事件隔离
调整
样式,避免滚动事件冲突:.file { margin: 0; position: fixed; top: 25px; left: 0; height: calc(100% - 25px); /* 修正top偏移导致的高度溢出 */ width: 100%; overflow-x: auto; overflow-y: hidden; pointer-events: none; /* 让滚动事件直接穿透到模拟容器 */ }内容的提问来源于stack exchange,提问作者KrystofCL
相关产品推荐
相关产品推荐

