我将<div>
s添加到包装器<div>
中,我需要能够每次添加到最后一个。我该如何在榆树中做到这一点?
<div class="messages" style="height: 7em; overflow: scroll">
<div>Anonymous: Hello</div>
<div>John: Hi</div>
</div>
直觉,似乎我可以调用运行JavaScript代码element.scrollTop = element.scrollHeight
的port
:
AddChatMessage chatMessage ->
( { model | chatMessages = model.chatMessages ++ [ chatMessage ] } , scrollToBottomPort "div.messages" )
问题是在更新model
之前,scrollToBottom
被称为。没什么大不了的,我将其转换为Task
。但是,即使model
现在首先更新,view
尚未更新。所以我最终从底部滚动到第二个项目!
这可能会导致一个更普遍的问题,我对ELM感到好奇,由于模型的更改,您如何在视图更新后运行Cmd
?
您可以使用端口滚动到列表的底部。
在这种情况下,您需要设置一个JavaScript以等待1个动画框架,然后再进行滚动。为了确保您的列表被渲染。
这样做的一种更简单的方法是使用Elm的Dom.scroll库。
并使用toBottom
函数。
如果将其包含在这样的代码中:
case msg of
Add ->
( model ++ [ newItem <| List.length model ]
, Task.attempt (always NoOp) <| Scroll.toBottom "idOfContainer"
)
NoOp ->
model ! []
它应该起作用。我在runelm.io
从ELM 0.19开始,使用功能Browser.Dom.getViewportOf
和Browser.Dom.setViewportOf
您可以每次添加新元素时都可以转到容器的底部。
jumpToBottom : String -> Cmd Msg
jumpToBottom id =
Dom.getViewportOf id
|> Task.andThen (info -> Dom.setViewportOf id 0 info.scene.height)
|> Task.attempt (_ -> NoOp)
dom.scroll绝对是必要的方法,并且易于实现。
- 设置要滚动的封闭html元素以具有独特的ID。
- 确保所述元素具有溢出的样式:滚动或Overflow-X:滚动。
- 从实际消息中发送命令 导致显示/打开的元素(消息 打开/显示元素,而您发射的命令将执行 滚动)。请注意,您使用命令是因为更改DOM在技术上是副作用。
查看文档以说滚动到底部: toBottom : Id -> Task Error ()
,您可以看到它需要是一项任务,因此您可以包装到Task.attempt
中。例如:
Task.attempt (_ -> NoOp) (Dom.Scroll.toBottom Id)
然后,您将需要一个函数将结果错误()转换为sg,但是由于滚动不太可能失败,要么几乎没有下跌,因此您可以设置像 (_ -> NoOp)
这样的虚拟函数作为快速骇客。
由于版本0.19 Dom
被弃用,您可以使用Html.Attribute.property
函数设置滚动位置。
示例
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" ]