没有href或使用空href的元素在Elm 0.19中使用Browser.application时会导致页面重新加载

gle*_*nsl 2 url-routing href elm

空链接,即a没有href属性的元素,href ""如果Browser.application在Elm 0.19中使用,则会导致页面重新加载.

这是一个最小,完整且可验证的示例:

module Main exposing (main)

import Browser
import Browser.Navigation
import Html exposing (..)
import Url


type alias Model =
    ()


type Msg
    = UrlRequested Browser.UrlRequest
    | UrlChanged Url.Url


init () _ _ =
    ( (), Cmd.none )


update msg model =
    case msg of
        UrlRequested (Browser.Internal _) ->
            ( model, Cmd.none )

        UrlRequested (Browser.External url) ->
            ( model, Browser.Navigation.load url )

        UrlChanged _ ->
            ( model, Cmd.none )


view model =
    { title = ""
    , body = [ a [] [ text "click to reload" ] ]
    }


main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = UrlRequested
        , onUrlChange = UrlChanged
        }
Run Code Online (Sandbox Code Playgroud)

这是非标准行为,因为用户代理不应将此类链接视为超链接,并且其中许多代码依赖于此行为elm-bulma.

gle*_*nsl 5

这是由Elm将onclick事件侦听器附加到所有a元素以便能够在内部拦截和处理路由引起的.它解析URL并将其分类为Internal或者External,其中href显然考虑了空或省略External.然后榆树将创建一个"消息"使用传递给类型构造Browser.application通过onUrlRequest', run更新passing thisMsg`,而这正是我们可以拦截并适当地处理它.

解决方案是添加另一个update匹配空外部URL的模式,我们根本不做任何事情,而不是load像通常使用其他外部URL那样尝试URL.关于问题的例子,下面更新的update函数应该可以解决问题:

update msg model =
    case msg of
        UrlRequested (Browser.Internal _) ->
            ( model, Cmd.none )

        UrlRequested (Browser.External "") ->
            ( model, Cmd.none )

        UrlRequested (Browser.External url) ->
            ( model, Browser.Navigation.load url )

        UrlChanged _ ->
            ( model, Cmd.none )
Run Code Online (Sandbox Code Playgroud)