You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tauri文件查看器单轴滚动阻塞另一轴的问题排查

问题排查与解决方案

核心原因分析

  1. 滚动事件高频触发+异步请求堆积:每次滚动都会触发lazy_redraw调用Rust后端,异步请求返回后更新DOM。快速滚动时,大量未完成的请求会集中更新DOM,抢占主线程资源,导致另一轴向滚动的事件处理被延迟。
  2. requestAnimationFrame滥用:之前的RAF写法会持续递归调用scrollHandler,即使没有滚动操作也一直在运行,持续占用主线程,加剧滚动卡顿。
  3. 滚动事件绑定对象混淆:如果滚动事件绑定在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:12:51