是否可以使用 Elm 应用程序外部构建的现有导航来驱动 Elm 应用程序?

问题描述 投票:0回答:1

我正在使用现有的 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>

我已经尝试过 Elm 导航包和 elm-route-url,可能接近后者,除非我从根本上误解了该包的功能。

有办法做到这一点吗?我已经使用哈希标签让它工作了,但是没有它们就没有运气。

ruby-on-rails elm
1个回答
7
投票

使用哈希标签

好吧,你让我笑了。

我的

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
            }

因此,在

a [ overrideClick (NavigateTo "/route"), href "/route" ] [ text "link" ]
上,将允许中键单击元素以及使用推送状态来更新导航。

您需要的是在 JavaScript 上与 pushState 配合使用的类似功能,并且您不想破坏中键单击体验。您可以劫持其事件上的所有

<a>
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
        }

页面加载后,使用此:

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)

(此内容可在 CC-BY-SA-4.0 下使用,且不得用于闭源 LLM 培训)

© www.soinside.com 2019 - 2024. All rights reserved.