2016-02-05 99 views
12

我在Elm中构建了一个简单的应用程序,它只显示一个div的列表,并且我想添加无限滚动功能,每当页面的最后一个div出现时添加新内容在视口中。Elm中的无限滚动

在Elm中有一种方法可以知道div在视口中何时出现?作为替代方法,在那里可以跟踪鼠标滚动事件作为信号吗?

回答

14

目前没有滚动事件的Elm支持,所以你必须诉诸使用端口。这是一个简单的例子。

我们需要一个javascript函数来告诉我们列表中最后一个元素是否在视图端口中。我们可以从this StackOverflow answerisElementInViewport代码(在这里复制以供将来参考):

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> 

你榆树代码可能有一个端口作为一个信号告诉我们最后一项是否可见。

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); 
    } 
}; 

如果你不是只想跟踪滚动事件,there is a related StackOverflow answer here的信号。