我的榆树应用程序使用自动滚动功能,它获取元素的Y位置并使用 Dom.Scroll.toY滚动到那里. 两个这样做,我设置了两个端口;订阅和发件人. ports.elm port setYofElementById : Maybe String - Cmd msgport ge
两个这样做,我设置了两个端口;订阅和发件人.
ports.elm
port setYofElementById : Maybe String -> Cmd msg port getYofElementById : (Value -> msg) -> Sub msg
的index.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
]
但是,这不会顺序发生.当动作首次触发时,没有任何反应.如果我再次触发它,它会滚动到第一个动作中要求的位置.所以它似乎是在设置值之前调用Dom.Scroll.toY.
有没有办法强制ScrollToY中的Cmds按顺序发生?或者有更好的方法来做到这一点吗?
您可以通过使第二个(执行Dom.Scroll.toY)作为对第一个(执行setYofElementById的响应)的响应来顺序执行Cmds.以下更新功能完成此操作: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)
在Cmds正确排序后,您需要确保Dom.Scroll.toY的newY参数位于正确的引用框架中以获得所需的效果.
