Elm中的无限滚动

12
我正在使用Elm构建一个简单的应用程序,它显示了一个垂直排列的div列表,并且我想要添加无限滚动功能,即在页面上最后一个div出现在视口中时添加新内容。Elm是否有一种方法可以知道一个div何时出现在视口中?作为替代方案,是否有一种方法可以跟踪鼠标滚动事件作为信号?
1个回答

14

目前Elm不支持滚动事件,所以您需要使用ports。这是一个简单的示例。

我们需要一个JavaScript函数来判断列表中的最后一个元素是否在视口中。 我们可以从这个StackOverflow答案中获取isElementInViewport代码(以下是拷贝的内容,供以后参考):

function isElementInViewport (el) {
    //special bonus for those using jQuery
    if (typeof jQuery === "function" && el instanceof jQuery) {
        el = el[0];
    }

    var rect = el.getBoundingClientRect();

    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
        rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
    );
}

假设你的HTML长这样:

<div class="wrapper">
  <div class="item">...</div>
  <div class="item">...</div>
</div>

你的 Elm 代码可以有一个端口作为信号,告诉我们最后一项是否可见。

port lastItemVisible : Signal Bool

现在你需要在JavaScript端连接端口代码。这段代码将监听window.onscroll事件,然后检查最后一个项目是否可见于.wrapper div中,并发送相应的信号。

var app = Elm.fullscreen(Elm.Main, {
  lastItemVisible: false
});

window.onscroll = function () {
  var wrapper = document.getElementsByClassName("wrapper")[0];
  var lastItem = wrapper.childNodes[wrapper.childNodes.length - 1];

  if (isElementInViewport(lastItem)) {
    app.ports.lastItemVisible.send(true);
  } else {
    app.ports.lastItemVisible.send(false);
  }
};

如果您只是想要一个用于跟踪滚动事件的信号,这里有一个相关的 StackOverflow 答案


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接