2016-12-15 68 views
12

我正在使用现有的Rails应用程序,导航必须继续在后端构建(由于复杂性和时间限制)。预期的结果是有一些使用Elm生成的页面,有些使用Rails,不使用哈希,也不使用整页重新加载(至少对于Elm页面)。导航的简化版本是这样的:是否有可能在Elm应用程序之外构建的现有导航驱动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-route-url,可能与后者即将关闭,除非我从根本上误解了包的能力。

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

+0

我认为这是可行的事件监听到你的锚链接连接到的preventDefault并通过端口来传递的意图,榆树 –

+0

@SimonH似乎是这样,我正在考虑这个选择。如果可能的话,我想看看如何留在Elm。 – scoots

回答

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" ]这将使中单击元素以及使用按压状态更新导航。

您需要的是与pushState一起使用的JavaScript类似的东西,而且您不想毁掉中间点击体验。您可以劫持其所有事件中的所有<a> s,preventDefault以停止浏览器导航,并通过目标的href推入新状态。您可以将导航的<a> s委托给事件处理程序。由于Navigation运行时不支持在外部监听历史记录更改(而似乎是使用效果管理器),所以必须将该值通过端口推送 - 幸运的是,如果您使用的是Navigation包,则应该已经有件。

在Elm端,使用UrlParser.parsePathNavigation programs之一结合使用。创建一个端口以订阅使用与其内部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) 
+0

谢谢,我已采纳您的建议。使用这种解决方案,是否需要使用标志或端口来使其完全正常工作?如果没有,你能否详细说明榆木会发生什么?到目前为止,我的更新没有被触发。 – scoots

+0

Arg ...是的,我挖入本机代码(https://github.com/elm-lang/navigation/blob/2.0.1/src/Native/Navigation.js),它并没有出现它听取改变事件。我已经用端口解决方案更新了主要答案。 – toastal

相关问题