sco*_*ots 12 ruby-on-rails elm
我正在使用现有的Rails应用程序,其中导航必须继续在后端构建(由于复杂性和时间限制).预期的结果是使用Elm生成一些页面,一些使用Rails,不使用哈希,也不使用整页重新加载(至少对于Elm页面).导航的简化版本如下所示:
<nav>
<a href="rails-page-1">...
<a href="rails-page-2">...
<a href="elm-page-1">...
<a href="elm-page-2">...
</nav>
<div id="elm-container"></div>
Run Code Online (Sandbox Code Playgroud)
我已经尝试过使用Elm导航软件包和elm-route-url,可能与后者接近,除非我从根本上误解了软件包的功能.
有没有办法实现这个目标?我已经使用哈希标签工作,但没有它们就没有运气.
使用哈希标签
好吧,你笑了我一顿.
我在我的Helpers.elm文件中有这个人,我可以用来代替Html.Events.click.
{-| Useful for overriding the default `<a>` behavior which
causes a refresh, but can be used anywhere
-}
overrideClick : a -> Attribute a
overrideClick =
Decode.succeed
>> onWithOptions "click"
{ stopPropagation = False
, preventDefault = True
}
Run Code Online (Sandbox Code Playgroud)
因此,a [ overrideClick (NavigateTo "/route"), href "/route" ] [ text "link" ]允许在中间单击元素以及使用推送状态来更新导航.
你需要的是类似于与pushState一起使用的JavaScript的东西,你不想破坏中键点击体验.您可以在其事件中劫持所有<a>s preventDefault以阻止浏览器导航,并通过目标的href推入新状态.您可以<a>在事件处理程序中委派导航.由于Navigation运行时不支持从外部监听历史记录更改(而不是使用效果管理器),因此您必须通过端口推送值 - 幸运的是,如果您使用的是Navigation包,那么您应该已经拥有碎片.
在Elm端,UrlParser.parsePath与其中一个Navigation程序一起使用.创建一个端口以使用与其内部URL更改相同的消息进行订阅.
import Navigation exposing (Location)
port externalPush : (Location -> msg) -> Sub msg
type Msg
= UrlChange Location
| ...
main =
Navigation.program UrlChange
{ ...
, subscriptions : \_ -> externalPush UrlChange
}
Run Code Online (Sandbox Code Playgroud)
页面加载后,使用:
const hijackNavClick = (event) => {
// polyfill `matches` if needed
if (event.target.matches("a[href]")) {
// prevent the browser navigation
event.preventDefault()
// push the new url
window.history.pushState({}, "", event.target.href)
// send the new location into the Elm runtime via port
// assuming `app` is the name of `Elm.Main.embed` or
// whatever
app.ports.externalPush.send(window.location)
}
}
// your nav selector here
const nav = document.querySelector("nav")
nav.addEventListener("click", hijackNavClick, false)
Run Code Online (Sandbox Code Playgroud)