onClick 消息导致不必要的页面刷新
onClick message causes unwanted refreshing of the page
我正在尝试用 Elm 建立一个网站,它包含几个更改语言的链接:
div [ class "language" ][ a [ class englishClass, onClick (ChangeLanguage English) ] [ text "EN" ]
, a [ class germanClass, onClick (ChangeLanguage German) ] [ text "DE" ]
, a [ class italianClass, onClick (ChangeLanguage Italian) ] [ text "IT" ]
]
我的更新是这样的:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
... -- Stuff for URLs
ChangeLanguage language ->
( { model | language = language }
, Cmd.none
)
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| ChangeLanguage Language
这是我的模型:
type alias Model =
{ key : Nav.Key
, url : Url.Url
, language : Language
}
这是我的初始化函数,它(至少在我看来)默认使用英语作为语言:
init : flags -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init _ url key = ( Model key url English, Cmd.none )
问题:
每当我单击更改语言的链接时,它们 确实 似乎有效:我看到页面中段落的语言发生了变化,但随后发生了一些不希望的事情:
- 页面刷新。由于我已经看到整个页面的语言变化,很明显这不是必需的,所以我想避免它。
- 作为 1 的结果,视口再次一直带到页面顶部。
- 语言再次更改为默认英文!
我怎样才能避免 1(以及 2)的发生?
我缺少什么才能使更改在整个网站上保持不变(至少在刷新页面时,因为我还没有尝试使用会话或 cookie)?
我认为此行为是 Elm 中的一个错误,并已提交 an issue for it, as have others with associated PRs。但是在一年半的时间里,没有人注意到任何能够真正对此做些什么的人,不幸的是,这与 Elm 的课程是一样的。
问题在于 Elm "hijacks" onClick
在 a
元素上创建导航事件,以便可以在 Elm 内部处理锚点。当使用 Browser.application
时,单击 a
元素将使 Elm 调用 onUrlReuqest
,值为 Browser.UrlRequest
,这将 class 或 URL 作为Internal
或 External
并要求您决定如何处理它。
问题的根源在于,省略 href
将生成 External
UrlRequest
,其中 URL 为空字符串。默认情况下,通过 External
的通常处理,这将告诉浏览器照常加载 URL,从而刷新页面。但它也表明一个可能的解决方法是特殊情况 External ""
:
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 )
另一种解决方法是将 href="#"
添加到 a
元素,这将正确地将它们 class 化为 Internal
我正在尝试用 Elm 建立一个网站,它包含几个更改语言的链接:
div [ class "language" ][ a [ class englishClass, onClick (ChangeLanguage English) ] [ text "EN" ]
, a [ class germanClass, onClick (ChangeLanguage German) ] [ text "DE" ]
, a [ class italianClass, onClick (ChangeLanguage Italian) ] [ text "IT" ]
]
我的更新是这样的:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
... -- Stuff for URLs
ChangeLanguage language ->
( { model | language = language }
, Cmd.none
)
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| ChangeLanguage Language
这是我的模型:
type alias Model =
{ key : Nav.Key
, url : Url.Url
, language : Language
}
这是我的初始化函数,它(至少在我看来)默认使用英语作为语言:
init : flags -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init _ url key = ( Model key url English, Cmd.none )
问题:
每当我单击更改语言的链接时,它们 确实 似乎有效:我看到页面中段落的语言发生了变化,但随后发生了一些不希望的事情:
- 页面刷新。由于我已经看到整个页面的语言变化,很明显这不是必需的,所以我想避免它。
- 作为 1 的结果,视口再次一直带到页面顶部。
- 语言再次更改为默认英文!
我怎样才能避免 1(以及 2)的发生?
我缺少什么才能使更改在整个网站上保持不变(至少在刷新页面时,因为我还没有尝试使用会话或 cookie)?
我认为此行为是 Elm 中的一个错误,并已提交 an issue for it, as have others with associated PRs。但是在一年半的时间里,没有人注意到任何能够真正对此做些什么的人,不幸的是,这与 Elm 的课程是一样的。
问题在于 Elm "hijacks" onClick
在 a
元素上创建导航事件,以便可以在 Elm 内部处理锚点。当使用 Browser.application
时,单击 a
元素将使 Elm 调用 onUrlReuqest
,值为 Browser.UrlRequest
,这将 class 或 URL 作为Internal
或 External
并要求您决定如何处理它。
问题的根源在于,省略 href
将生成 External
UrlRequest
,其中 URL 为空字符串。默认情况下,通过 External
的通常处理,这将告诉浏览器照常加载 URL,从而刷新页面。但它也表明一个可能的解决方法是特殊情况 External ""
:
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 )
另一种解决方法是将 href="#"
添加到 a
元素,这将正确地将它们 class 化为 Internal