jQuery动画/滚动仅部分适用于第二次单击

时间:2016-05-25 07:55:07

标签: jquery animation scrolltop elm

当我使用jQuery为滚动行为设置动画时,第一次单击将使视图直接跳转到单击的锚元素。 第二次点击,如果在动画延迟内发出,将完美无缺。 如果动画延迟用完并且再次发出一次点击,它将再次直接跳转到该元素。

这是一个简短的GIF演示了这个问题: enter image description here

如您所见,我点击services然后立即跳转。我等到动画延迟消失并点击portfolio,再次即时跳转。但是我再次快速点击services(动画延迟还没有运行),它按预期工作。

我的Elm-Application将onClick个事件分配给某些元素。触发后,元素的href将通过端口传递给JavaScript函数,如下所示:

-- partial view
view =
    div []
        [ nav [ class "navbar navbar-default navbar-fixed-top" ]
            [ div [ class "container" ]
                [ div [ class "navbar-header page-scroll" ]
                    [ button [ class "navbar-toggle", attribute "data-target" "#bs-example-navbar-collapse-1", attribute "data-toggle" "collapse", type' "button" ]
                        [ span [ class "sr-only" ]
                            [ text "Toggle navigation" ]
                        , span [ class "icon-bar" ]
                            []
                        , span [ class "icon-bar" ]
                            []
                        , span [ class "icon-bar" ]
                            []
                        ]
                    , a [ class "navbar-brand page-scroll", href "#page-top", onClick (Update.ClickedElem "#page-top") ]
                        [ text "Start Bootstrap" ]
                    ]
                , div [ class "collapse navbar-collapse", id "bs-example-navbar-collapse-1" ]
                    [ ul [ class "nav navbar-nav navbar-right" ]
                        [ li [ class "hidden" ]
                            [ a [ href "#page-top" ]
                                []
                            ]
                        , li []
                            [ a [ class "page-scroll", href "#services", onClick (Update.ClickedElem "#services") ]
                                [ text "Services" ]
                            ]
                        , li []
                            [ a [ class "page-scroll", href "#portfolio", onClick (Update.ClickedElem "#portfolio") ]
                                [ text "Portfolio" ]
                            ]
                        , li []
                            [ a [ class "page-scroll", href "#about", onClick (Update.ClickedElem "#about") ]
                                [ text "About" ]
                            ]
                        , li []
                            [ a [ class "page-scroll", href "#team", onClick (Update.ClickedElem "#team") ]
                                [ text "Team" ]
                            ]
                        , li []
                            [ a [ class "page-scroll", href "#contact", onClick (Update.ClickedElem "#contact") ]
                                [ text "Contact" ]
                            ]
                        ]
                    ]
                , text "  "
                ]
            ]
        , section [ id "services" ]
            [-- More content
            ]
          -- Much more content
        , section [ id "contact" ]
            [-- More content
            ]
        ]

-- partial update
 case msg of
    ClickedElem elem ->
        -- Sends the clicked element '#services' to the JS world
        ( model, clickedElem elem )

    ChangeLocation newLocation ->
        ( { model
            | location = newLocation
          }
        , Cmd.none
        )


-- the port
port clickedElem : String -> Cmd msg
port changeLoc : (String -> msg) -> Sub msg


-- subscription
subscriptions model =
    Sub.batch
        [ Window.resizes Update.Resize
        , Update.changeLoc Update.ChangeLocation
        ]

在JS端,我然后使用jQuery animate / scrollTo函数,如下所示:

<script>
  app.ports.clickedElem.subscribe(function(id){
    console.log("Scrolling.");
    // Why isn't this working properly?
    $('html, body').animate({
      scrollTop: $(id).offset().top
    }, 2000);
    // return false;
    app.ports.changeLoc.send(id);
  });
</script>

最后,新位置通过名为changeLoc的端口传回Elm,该端口只更新我的模型。

我在这里缺少什么?这是一个由于榆树虚拟的问题吗?我似乎无法解决这个问题。 提供的锚点的偏移量都很好,并且函数可以被调用。

以下是解决此问题的方法: 我没有使用onClick,而是使用@ChadGilbert的提示,然后转到onWithOptions,我将preventDefault设置为True。 结果:

onWithOptions "click" { stopPropagation = True, preventDefault = True } (Json.succeed (Update.ClickedElem "#anchor"))

而不是

onClick (Update.ClickedElem "#anchor")

谢谢!

1 个答案:

答案 0 :(得分:1)

标题中的链接是使用onClick创建的,因为您正在设置href参数,所以该事件将冒出来由浏览器处理,这就是您立即获取的原因跳。

在Javascript中,禁用默认浏览器行为和事件传播的方法是使用event.stopPropagation()event.preventDefault()

在Elm中,您可以使用onWithOptions创建设置这些值的事件属性。在Elm代码处理后,您可以使用以下代替onClick来禁止对click事件的任何进一步处理:

onClickFullStop : msg -> Html.Attribute msg
onClickFullStop =
  let fullStop = { stopPropagation = True, preventDefault = True }
  in onWithOptions "click" fullStop << Json.Decode.succeed