【问题标题】:Prevent viewport from moving when removing DOM elements移除 DOM 元素时防止视口移动
【发布时间】:2019-05-30 12:40:52
【问题描述】:

我正在尝试实现一个 HTML 无限滚动器,其中在任何给定时间列表中只有少数 div 元素(以保持较小的内存占用)。

我将一个新的 div 元素添加到列表中,同时我删除了第一个,因此 div 的总数保持不变。

不幸的是,视口并没有保持静止,而是向后跳跃了一点(实际上是删除的 div 的高度)。 有没有办法在从列表中删除 div 时保持视口静止?

我制作了一个小型的自包含 HTML 页面(好吧,它仍然需要 JQuery 3.4.1),它暴露了问题:它首先添加 5 个 div,然后不断添加一个新的 div,并每隔 1 秒删除第一个

function getRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function removeit() {
  // remove first one
  var tiles = $(".tile");
  $(tiles[0]).remove();
}

function addit() {
  // append new one
  var jqueryTextElem = $('<div class="tile" style="height:100px;background-color:' + getRandomColor() + '"></div>');
  $("#inner-wrap").append(jqueryTextElem);
}

function loop() {
  removeit();

  addit();

  window.setTimeout(loop, 1000);
}

addit();
addit();
addit();
addit();
addit();

loop();
<div id="inner-wrap"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

【问题讨论】:

  • 如果您删除顶部div,猜猜新顶部div 是什么?下一个,强制浏览器重新绘制,从而产生跳跃效果。 IMO,您正在让浏览器做更多的工作,您应该保持外部 div 不变,如果您更关心额外的 DOM 元素,则可以删除内部内容。
  • @Rikin 我真正想要实现的是一个无限滚动器,在该滚动器中,我在底部添加了一个 div,然后删除了顶部的 div,从而保持 div 计数较低。暂时我只会处理向下滚动。下一步将向上,这意味着在顶部添加一个新 div 并在底部删除一个。
  • 是的,因此您必须为旧 div 保留不动产,除非您不打算在网页上设置滚动条,在这种情况下,视口中的顶部 div 始终位于首位。
  • @Rikin 有趣,您能否详细说明或修复示例?

标签: javascript jquery html css scroll


【解决方案1】:

您可以暂时将position: fixed添加到父元素中:

  1. 先将position: fixed添加到父级;
  2. 然后删除该项目;
  3. 然后从父级中删除position: fixed

【讨论】:

  • 这是如何工作的?添加 position:fixed 从视图中移除父元素
  • @mss - 我希望我能提供帮助,但首先,我需要澄清你的问题。您是说:“这种方法对我不起作用”还是说:“我看到这种方法有效,但如何起作用?”
  • 两者。这种方法显然对我不起作用,但是由于这个答案被标记为已接受,因此这种方法似乎适用于 OP,所以我很好奇这种方法是如何工作的,在知道也许我可以使这种方法适用于我:)
【解决方案2】:

我有一种感觉,你想吃蛋糕,如果你让视口“静止”,我认为你的意思是你不希望用户看到滚动条移动然后也没有任何新的功能可以进一步向下滚动页面,因为您希望滚动条拇指/抓取器仍位于滚动条轨道的底部?

我的意思是,您可以在示例中使用$(window).scrollTop($(window).scrollTop() + 100); 来制作它,以便在删除元素时视口的滚动位置不会在视觉上移动,但此时您不会让用户查看当前元素相同,甚至允许用户在页面下方滚动新内容。您只是通过用户的视图“推送”内容?

如果您试图减轻当前解析为文档的负载,因为您在运行时对文档对象进行了一些繁重的工作,那么您可能仍想删除较早的元素,但使用一些空的哨兵元素保留它们的几何形状总是将所有先前删除的元素的高度添加到它?这将允许您拥有更小的占用空间(尽管不是布局方式),同时仍然有一个可以与用户交流的可用滚动条,并且都允许用户向下滚动到已添加的内容。

总而言之,我认为您目前拥有的是大多数无限滚动条的工作方式和应该如何工作,这意味着当向用户滚动的方向添加内容时,滚动位置和滚动条应该改变,这向他们传达了他们实际上可以继续滚动。您真的不应该希望视口滚动位置“静止”。

要更清楚地了解为什么我认为您没有实际问题,请将您的 loop() 定义替换为类似这样的定义...

function loop() {
  $(window).scroll(function() {
    // check for reaching bottom of scroller
    if ($(window).scrollTop() == ($(document).height() - $(window).height())) {
      addit();
      removeit();
    }
  })
}

【讨论】:

  • 实际上,这是刚刚编写的一个不错的参考资料,虽然它是在讨论这个的反应版本,但它阐述了这些事情如何/为什么以它们的方式工作。 web.dev/virtualize-long-lists-react-window
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多