如何在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.19Dom
已被弃用,您可以使用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)