在 Elm 0.19 中使用 Browser.application 时,没有 href 或 href 为空的元素会导致页面重新加载
a elements without href, or with an empty href, causes page reload when using Browser.application in Elm 0.19
空链接,即 a
没有 href
属性或带有 href ""
的元素,如果在 Elm 0.19 中与 Browser.application
一起使用,会导致页面重新加载。
这是一个最小的、完整的和可验证的例子:
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
}
这是非标准行为,因为用户代理不应将此类链接视为超链接,并且很多代码都依赖于此行为,其中 elm-bulma
.
这是因为 Elm 将 onclick
事件侦听器附加到所有 a
元素,以便能够在内部拦截和处理路由。它解析 URL 并将其分类为 Internal
或 External
,其中空的或省略的 href
显然被视为 External
。然后,Elm 将使用通过 onUrlRequest
传递给 Browser.application
的类型构造函数创建一个 'Msg',运行 update
传递此 Msg
,这就是我们可以适当拦截和处理。
解决方案是向 update
添加另一个匹配空外部 URL 的模式,我们只是什么都不做,而不是尝试 load
和 URL 作为我们通常会使用其他外部 URLs。关于问题的示例,以下更新的 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 )
另一种只涉及视图功能的解决方案是将 a
元素的属性 target
设置为 _self
,在这种情况下 Elm 将不会离开。
中有一个关于此问题的未解决问题
空链接,即 a
没有 href
属性或带有 href ""
的元素,如果在 Elm 0.19 中与 Browser.application
一起使用,会导致页面重新加载。
这是一个最小的、完整的和可验证的例子:
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
}
这是非标准行为,因为用户代理不应将此类链接视为超链接,并且很多代码都依赖于此行为,其中 elm-bulma
.
这是因为 Elm 将 onclick
事件侦听器附加到所有 a
元素,以便能够在内部拦截和处理路由。它解析 URL 并将其分类为 Internal
或 External
,其中空的或省略的 href
显然被视为 External
。然后,Elm 将使用通过 onUrlRequest
传递给 Browser.application
的类型构造函数创建一个 'Msg',运行 update
传递此 Msg
,这就是我们可以适当拦截和处理。
解决方案是向 update
添加另一个匹配空外部 URL 的模式,我们只是什么都不做,而不是尝试 load
和 URL 作为我们通常会使用其他外部 URLs。关于问题的示例,以下更新的 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 )
另一种只涉及视图功能的解决方案是将 a
元素的属性 target
设置为 _self
,在这种情况下 Elm 将不会离开。