Elm 中的 Browser.Navigation.Key *是什么?
What *is* a Browser.Navigation.Key in Elm?
我开始使用 Elm 的 Browser.application
,这很有趣,但是(据我所知)从未真正解释过的一件事是 Browser.Navigation.Key
类型。
A navigation Key is needed to create navigation commands that change the URL. That includes pushUrl, replaceUrl, back, and forward.
而且我认为在这一点上我想我已经从 elm 指南中的以下示例中了解了如何使用它,但我很好奇,只是学术上的:
- 这种类型包含什么样的信息?
- elm 的导航在内部如何使用这些信息?
我有一段时间没有使用 Elm,但我自己对此很好奇。
乍一看,关键机制解决了此处概述的问题:https://github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md — 或者至少与该争论有关。
直接得出的结论是,他们想禁止您访问 URL 变化的 API,除非您使用 Browser.application
创建您的应用程序,所以一种方法是要求像 Key
这样的虚拟类型作为输入,只有使用 Browser.application
才能获得。但关键还不止于此。
与 Browser.document
和 Browser.element
不同,Browser.application
为您提供额外的处理程序:onUrlRequest
和 onUrlChange
.
那么,当 URL 发生变化时,它是如何与您的应用程序通信的?它是如何实现的?
特别是 Key
不透明类型中包含的内容:
var key = function() { key.__sendToApp(onUrlChange(_Browser_getUrl())); };
当您使用 Browser.application
时,初始化代码连接 url-更改侦听器以调用 key()
:
_Browser_window.addEventListener('popstate', key);
_Browser_window.addEventListener('hashchange', key);
和URL-改变函数也调用key()
:
var _Browser_pushUrl = F2(function(key, url)
{
return A2(__Task_perform, __Basics_never, __Scheduler_binding(function() {
history.pushState({}, '', url);
key();
}));
});
密钥机制是 API 知道将 URL 更改更新路由到何处的一种简单方法:简单,代码要求您为其提供 key
函数将在创建它的应用程序上调用 app.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
换句话说,似乎关键机制是作为 go
、pushUrl
、replaceUrl
函数 (https://github.com/elm/browser/blob/53e3caa265fd9da3ec9880d47bb95eed6fe24ee6/src/Elm/Kernel/Browser.js#L190-L212) 的简单无状态方式存在的调用当前 运行 应用程序的 onUrlChange
的方法。否则 API 可能只用 Browser.application
初始化中的 _Browser_window.addEventListener('popstate', key)
行就可以了。但是当 URL 从 Javascript 更改时,该事件永远不会发出,因此他们需要一种方法来直接在这些函数内部调用 app.onUrlChange()
,也就是 key()
.
当然,它还有一个额外的好处,那就是将 URL API 的范围限定为仅使用 Browser.application
创建的应用程序。有点漫无边际的答案,但我没有时间写一个较短的答案。 ;)
我开始使用 Elm 的 Browser.application
,这很有趣,但是(据我所知)从未真正解释过的一件事是 Browser.Navigation.Key
类型。
A navigation Key is needed to create navigation commands that change the URL. That includes pushUrl, replaceUrl, back, and forward.
而且我认为在这一点上我想我已经从 elm 指南中的以下示例中了解了如何使用它,但我很好奇,只是学术上的:
- 这种类型包含什么样的信息?
- elm 的导航在内部如何使用这些信息?
我有一段时间没有使用 Elm,但我自己对此很好奇。
乍一看,关键机制解决了此处概述的问题:https://github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md — 或者至少与该争论有关。
直接得出的结论是,他们想禁止您访问 URL 变化的 API,除非您使用 Browser.application
创建您的应用程序,所以一种方法是要求像 Key
这样的虚拟类型作为输入,只有使用 Browser.application
才能获得。但关键还不止于此。
Browser.document
和 Browser.element
不同,Browser.application
为您提供额外的处理程序:onUrlRequest
和 onUrlChange
.
那么,当 URL 发生变化时,它是如何与您的应用程序通信的?它是如何实现的?
特别是 Key
不透明类型中包含的内容:
var key = function() { key.__sendToApp(onUrlChange(_Browser_getUrl())); };
当您使用 Browser.application
时,初始化代码连接 url-更改侦听器以调用 key()
:
_Browser_window.addEventListener('popstate', key);
_Browser_window.addEventListener('hashchange', key);
和URL-改变函数也调用key()
:
var _Browser_pushUrl = F2(function(key, url)
{
return A2(__Task_perform, __Basics_never, __Scheduler_binding(function() {
history.pushState({}, '', url);
key();
}));
});
密钥机制是 API 知道将 URL 更改更新路由到何处的一种简单方法:简单,代码要求您为其提供 key
函数将在创建它的应用程序上调用 app.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
换句话说,似乎关键机制是作为 go
、pushUrl
、replaceUrl
函数 (https://github.com/elm/browser/blob/53e3caa265fd9da3ec9880d47bb95eed6fe24ee6/src/Elm/Kernel/Browser.js#L190-L212) 的简单无状态方式存在的调用当前 运行 应用程序的 onUrlChange
的方法。否则 API 可能只用 Browser.application
初始化中的 _Browser_window.addEventListener('popstate', key)
行就可以了。但是当 URL 从 Javascript 更改时,该事件永远不会发出,因此他们需要一种方法来直接在这些函数内部调用 app.onUrlChange()
,也就是 key()
.
当然,它还有一个额外的好处,那就是将 URL API 的范围限定为仅使用 Browser.application
创建的应用程序。有点漫无边际的答案,但我没有时间写一个较短的答案。 ;)