什么 * 是 * Elm 中的 Browser.Navigation.Key?

Ele*_*ley 11 elm

我开始与 Elm 一起工作,Browser.application这很有趣,但是(据我所知)从未真正解释过的一件事是Browser.Navigation.Key类型。

榆树文档

需要一个导航键来创建更改 URL 的导航命令。这包括 pushUrl、replaceUrl、后退和前进。

我认为在这一点上,我认为我几乎可以从 elm 指南中的以下示例中了解如何使用它,但我很好奇,只是在学术上:

  • 这种类型包含什么样的信息?
  • elm 的导航在内部如何使用这些信息?

dan*_*neu 17

我有一段时间没有使用 Elm,但我自己对此很好奇。

乍一看,关键机制解决了此处概述的问题:https : //github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md——或者至少与此有关争执。

眼前的外卖是他们想访问的URL变化的API禁止你,除非你创建了您的应用程序Browser.application,这样一个办法做到这一点是需要一个虚拟的类型像Key作为输入,如果你使用你只能得到Browser.application。但关键还不止于此。

Browser.application,与Browser.documentand不同Browser.element,为您提供额外的处理程序:onUrlRequestand onUrlChange

那么,当 URL 更改时,它是如何传达给您的应用程序的呢?它是如何实施的?

这里的源代码解释了很多:https : //github.com/elm/browser/blob/53e3caa265fd9da3ec9880d47bb95eed6fe24ee6/src/Elm/Kernel/Browser.js#L142

特别是,这是Keyopaque 类型中的内容:

var key = function() { key.__sendToApp(onUrlChange(_Browser_getUrl())); };
Run Code Online (Sandbox Code Playgroud)

当您使用 时Browser.application,初始化代码会连接 url-change 侦听器以调用key()

_Browser_window.addEventListener('popstate', key);
_Browser_window.addEventListener('hashchange', key);
Run Code Online (Sandbox Code Playgroud)

URL 更改函数也调用key()

var _Browser_pushUrl = F2(function(key, url)
{
    return A2(__Task_perform, __Basics_never, __Scheduler_binding(function() {
        history.pushState({}, '', url);
        key();
    }));
});
Run Code Online (Sandbox Code Playgroud)

关键机制是 API 知道将 URL 更改更新路由到何处的简单方法:简单,代码要求您为其提供keyapp.onUrlChange(...)在创建它的应用程序上调用的函数。

这似乎仍然没有完全回答我问题的一个技术部分:为什么你需要将键传递给 Navigation.{go,push,replace}?当 URL 更改时,上面的代码 ( _Browser_window.addEventListener('popstate', key))不是已经调用key()了吗?

事实证明,该popstate事件仅针对 UI 交互(例如单击后退按钮)触发。history.{push,replace}State(..., url)直接使用时不会调用该事件,这当然是该库正在执行的操作:https : //developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate

换句话说,它似乎是关键机制的存在作为一个简单的无状态的方式为gopushUrlreplaceUrl功能(https://github.com/elm/browser/blob/53e3caa265fd9da3ec9880d47bb95eed6fe24ee6/src/Elm/Kernel/Browser.js#L190-L212 ) 来调用当前运行的应用程序的onUrlChange. 否则,API 可能只需要初始化_Browser_window.addEventListener('popstate', key)一行就可以了Browser.application。但是当 URL 从 Javascript 更改时永远不会发出该事件,因此他们需要一种app.onUrlChange()直接在这些函数内部调用的方法,也就是key().

而且,当然,它具有将 URL API 限定为仅使用Browser.application. 有点乱七八糟的答案,但我没有时间写一个更短的答案。;)