问题描述
我开始使用 Elm 的 browser.application
,这很有趣,但是(据我所知)从未真正解释过的一件事是 browser.Navigation.Key
类型。>
需要导航键来创建更改 URL 的导航命令。这包括 pushUrl、replaceUrl、后退和前进。
而且我认为在这一点上,我认为我几乎可以从 elm 指南中的以下示例中了解如何使用它,但我很好奇,只是在学术上:
- 这种类型包含哪些类型的信息?
- elm 的导航在内部如何使用这些信息?
解决方法
我有一段时间没有使用 Elm,但我自己对此很好奇。
乍一看,关键机制解决了此处概述的一个问题:https://github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md — 或者至少与该争用有关。
最直接的结论是,除非您使用 Browser.application
创建应用,否则他们希望禁止您访问 URL 更改 API,因此一种方法是要求使用 {{1} 之类的虚拟类型} 作为输入,只有使用 Key
才能获得。但关键还不止于此。
Browser.application
与 Browser.application
和 Browser.document
不同,为您提供了额外的处理程序:Browser.element
和 onUrlRequest
。
那么,当 URL 更改时,它是如何与您的应用程序通信的?它是如何实施的?
这里的源代码解释了很多:https://github.com/elm/browser/blob/53e3caa265fd9da3ec9880d47bb95eed6fe24ee6/src/Elm/Kernel/Browser.js#L142
特别是,这就是 onUrlChange
不透明类型中的内容:
Key
当您使用 var key = function() { key.__sendToApp(onUrlChange(_Browser_getUrl())); };
时,初始化代码会连接 url-change 侦听器以调用 Browser.application
:
key()
URL 更改函数也调用 _Browser_window.addEventListener('popstate',key);
_Browser_window.addEventListener('hashchange',key);
:
key()
关键机制是 API 知道将 URL 更改更新路由到何处的简单方法:简单,代码要求您为其提供 var _Browser_pushUrl = F2(function(key,url)
{
return A2(__Task_perform,__Basics_never,__Scheduler_binding(function() {
history.pushState({},'',url);
key();
}));
});
函数,该函数将在应用程序上调用 key
创造了它。
这似乎仍然没有完全回答我问题的一个技术部分:为什么你需要将键传递给 Navigation.{go,push,replace}?当 URL 更改时,上面的代码 (app.onUrlChange(...)
) 不是已经调用了 _Browser_window.addEventListener('popstate',key)
吗?
事实证明,key()
事件仅针对 UI 交互(例如单击后退按钮)触发。当您直接使用 popstate
时不会调用该事件,这当然是该库正在执行的操作:https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate
换句话说,对于 history.{push,replace}State(...,url)
、go
、pushUrl
函数 (https://github.com/elm/browser/blob/53e3caa265fd9da3ec9880d47bb95eed6fe24ee6/src/Elm/Kernel/Browser.js#L190-L212) 来说,密钥机制似乎是作为一种简单的无状态方式存在的调用当前运行的应用程序的 replaceUrl
。否则 API 可能会在 onUrlChange
初始化中仅使用 _Browser_window.addEventListener('popstate',key)
行。但是当 URL 从 Javascript 更改时永远不会发出该事件,因此他们需要一种方法来直接在这些函数中调用 Browser.application
,也就是 app.onUrlChange()
。
当然,它还具有将 URL API 限定为仅使用 key()
创建的应用程序的额外回报。有点乱七八糟的答案,但我没有时间写一个更短的答案。 ;)