我的榆树应用程序使用自动滚动功能,它获取元素的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参数位于正确的引用框架中以获得所需的效果.