如何使用defineSetter在两个对象中正确设置scrollLeft?

Was*_*des 8 javascript performance scroll

在我的页面中,我有两个相同宽度的表,它们都进行水平滚动.当每个表滚动时,我需要将两个表设置为相同的位置.

实际上,我的代码是:

var scrollA = $('#scrollA'),
    scrollB = $('#scrollB');

scrollA.on('scroll', function() {
    scrollB[0].scrollLeft = scrollA[0].scrollLeft;
});
Run Code Online (Sandbox Code Playgroud)

有用.问题是,在某些情况下,加载的数据足以使浏览器和滚动事件变慢.

然后,我正在努力改善那些情况下的用户体验.


我做了这个片段,我尝试使用以下__defineSetter__功能Object:

var elementA = { scrollLeft: 30 },
    elementB = { scrollLeft: 30 };

elementA.__defineSetter__('scrollLeft', val => elementB.scrollLeft = val);

elementA.scrollLeft += 5;
console.log(elementA.scrollLeft + ' == ' + elementB.scrollLeft);
Run Code Online (Sandbox Code Playgroud)

但是你可以看到运行的片段,将其设置undefined到elementA.scrollLeft和NaN到elementB.scrollLeft.

我想在这里给你一些指导,谢谢你的时间.

jbm*_*nez 2

滚动事件可以以很高的速率触发,因此您可以通过限制滚动事件处理程序来获得更平滑的滚动,正如 trincot 在他的回答中所说。您可以使用 来限制函数setTimeout。不过,当在屏幕上移动物体或处理其他可见效果时,我更喜欢requestAnimationFrame.

requestAnimationFrame在下次重绘之前运行回调,以便浏览器可以进行一些优化。

此代码将使您更接近解决方案,它基于MDN 的以下示例:

var scrollA = $('#scrollA'),
    scrollB = $('#scrollB'),
    running = false;

scrollA.on('scroll', function() {
  // if we already requested an animation frame, do nothing
  if (!running) {
    window.requestAnimationFrame(function() {
      // synchronize table B and table A
      scrollB[0].scrollLeft = scrollA[0].scrollLeft
      // we're done here and can request a new frame
      running = false;
    });
  }

  running = true;
});
Run Code Online (Sandbox Code Playgroud)

您可以使用传递给回调的时间戳来进一步消除同步,但如果您延迟太多,则第二个表中的滚动可能会有点缓慢。