我的 elm 应用程序使用自动滚动功能,它获取元素的 Y 位置并使用 Dom.Scroll .toY 在那里滚动。
两个做这个,我设置了两个端口;订阅和发件人。
端口文件
port setYofElementById : Maybe String -> Cmd msg
port getYofElementById : (Value -> msg) -> Sub msg
索引.html
app.ports.setYofElementById.subscribe(function(id) {
var element = document.getElementById(id);
var rect = element.getBoundingClientRect();
app.ports.getYofElementById.send({"number": rect.top});
})
监听器是订阅
subscriptions : Model -> Sub Msg
subscriptions model =
Ports.getYofElementById getYofElementById
getYofElementById : Decode.Value -> Msg
getYofElementById value =
let
result =
Decode.decodeValue bSimpleIntValueDecoder value
in
case result of
Ok simpleIntValue ->
SetSelectedElementYPosition (Just simpleIntValue.number)
Err id ->
SetSelectedElementYPosition Nothing
SetSelectedElementYPosition
只是设置模型。现在,执行此操作的操作做了两件事:调用
Port.setYofElementById
,然后滚动到模型中的 Y 值,假设它已被设置。update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ScrollToY idString ->
model
=> Cmd.batch
[ Ports.setYofElementById (Just idString)
, Task.attempt (always NoOp) <| Dom.Scroll.toY "ul" model.selectedElementYPosition
]
但是,这不会按顺序发生。当 Action 第一次触发时,什么也没有发生。如果我再次触发它,它会滚动到第一个操作中调用的位置。所以它似乎在调用
Dom.Scroll.toY
在设置值之前。有没有办法强制
Cmd
s 在 ScrollToY
依次发生?或者有没有更好的方法来做到这一点?
最佳答案
您可以获得 Cmd
s 通过使第二个执行 Dom.Scroll.toY
来按顺序执行,作为对第一个的响应发生,即执行 setYofElementById
的那个.下面的更新函数实现了这一点:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ScrollToY idString ->
(model, Ports.setYofElementById idString)
SetSelectedElementYPosition (Just newY) ->
(model, Task.attempt (always NoOp) <| Dom.Scroll.toY "ul" newY)
SetSelectedElementYPosition Nothing ->
(model, Cmd.none)
NoOp ->
(model, Cmd.none)
与
Cmd
s 正确排序,您需要确保 newY
论据 Dom.Scroll.toY
处于正确的引用系中以获得您想要的效果。
关于elm - 从 Elm 端口检索 DOM 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48367539/