如何在Elm中自动滚动到div的底部

如何在Elm中自动滚动到div的底部,elm,elm-port,Elm,Elm Port,我将添加到包装器,并且我需要能够滚动到每次添加的最后一个。在Elm我该怎么做 <div class="messages" style="height: 7em; overflow: scroll"> <div>Anonymous: Hello</div> <div>John: Hi</div> </div> 问题是scrollToBottom在模型更新之前被调用。所以没什么大不了的,我把它转换成一个任务。但是,即使

我将
添加到包装器
,并且我需要能够滚动到每次添加的最后一个。在Elm我该怎么做

<div class="messages" style="height: 7em; overflow: scroll">
  <div>Anonymous: Hello</div>
  <div>John: Hi</div>
</div>
问题是
scrollToBottom
模型更新之前被调用。所以没什么大不了的,我把它转换成一个
任务
。但是,即使现在先更新了
模型
视图
也没有更新。因此,我最终从底部滚动到第二项


这可能会引出我在Elm中很好奇的一个更一般的问题,在视图由于模型的更改而更新之后,如何运行
Cmd

您可以使用端口滚动到列表的底部。
在这种情况下,需要将javascript设置为在执行滚动之前等待1个AnimationFrame。以确保列表已呈现

更简单的方法是使用Elm的库。
并使用
toBottom
功能

如果将其包含在代码中,如下所示:

case msg of
    Add ->
        ( model ++ [ newItem <| List.length model ]
        , Task.attempt (always NoOp) <| Scroll.toBottom "idOfContainer"
        )

    NoOp ->
        model ! []
消息的大小写
添加->
(model++[newItem无疑是一种可行的方法,并且易于实现

  • 将要滚动的封闭HTML元素设置为具有不同的 身份证
  • 确保所述元素的样式为overflow-y:scroll或 溢出x:滚动
  • 从任何消息发送命令 导致显示/打开该元素(消息 打开/显示元素,而您发出的命令将执行以下操作: 注意,您使用命令是因为从技术上讲,更改DOM是一种副作用
  • 查看文档,例如滚动到底部:
    toBottom:Id->Task Error()
    ,您可以看到它需要是一个任务,因此您可以将其包装到
    任务中。尝试
    。例如:
    
    Task.trument(\ \ \->NoOp)(Dom.Scroll.toBottom Id)
    


    然后,您需要一个函数将结果错误()转换为消息,但由于滚动不太可能失败,或者如果失败,则几乎没有负面影响,因此您可以设置一个伪函数,如
    (\ \ \->NoOp)
    作为一种快速破解方法。

    由于版本0.19
    Dom
    已被弃用,您可以使用
    Html.Attribute.property
    函数设置滚动位置

    例子
    从Elm 0.19开始,使用函数,每次添加新元素时都可以转到容器底部

    jumpToBottom : String -> Cmd Msg
    jumpToBottom id =
        Dom.getViewportOf id
            |> Task.andThen (\info -> Dom.setViewportOf id 0 info.scene.height)
            |> Task.attempt (\_ -> NoOp)
    

    你可以看看官方的TodoMVC elm应用程序。我想它就是这么做的。(现在在手机上,否则会有共享链接)@wintvelt,这是TodoMVC Elm应用程序:。我在那里没有看到任何关于滚动的内容,只有一个
    Dom.focus
    调用。
    index.html
    和CSS文件也没有提供任何自动滚动的指示。你说得对。它不在TodoMVC应用程序中。我的错。将在下面添加一个答案。不知道
    Dom.Scroll
    !谢谢。我以前尝试过
    任务。使用JavaScript
    端口调用执行
    ,JavaScript没有看到最后一项。我想知道这是否是因为
    Dom.Scroll
    在虚拟Dom上工作,因此它可以看到最后一项并向下滚动到它。而JavaScript还看不到真正的Dom正在更新…而不是
    (\ \ \->NoOp)
    ,write
    始终NoOp
    始终
    是此常见模式的包装器:-).Dom deprecated来自。我认为您的答案不适用。问题是关于从更新函数滚动。我同意您的观点,但我不希望在模型逻辑中操纵Dom。对我来说,在更新中进行计算完全可以,但将计算值设置为元素,这应该是视图关注的问题。
    import Html exposing (Html, text)
    import Html.Attributes exposing (class, property)
    import Json.Encode as Encode
    
    
    view : Model -> Html Msg
    view model =
        div [ class "flow-editor"
            , property "scrollLeft" (Encode.float model.scrollLeft)
            , property "scrollTop" (Encode.float model.scrollTop)
            ]
            [ text "placeholder" ]
    
    jumpToBottom : String -> Cmd Msg
    jumpToBottom id =
        Dom.getViewportOf id
            |> Task.andThen (\info -> Dom.setViewportOf id 0 info.scene.height)
            |> Task.attempt (\_ -> NoOp)