【问题标题】:What *is* a Browser.Navigation.Key in Elm?什么*是* Elm 中的 Browser.Navigation.Key?
【发布时间】:2021-02-22 01:38:13
【问题描述】:

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

The elm docs

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

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

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

【问题讨论】:

    标签: elm


    【解决方案1】:

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

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

    直接的收获是,他们希望禁止您访问 URL 更改 API,除非您使用 Browser.application 创建您的应用程序,因此一种方法是要求像 Key 这样的虚拟类型作为输入只有使用Browser.application 才能获得。但关键还不止于此。

    Browser.applicationBrowser.documentBrowser.element 不同,它为您提供额外的处理程序:onUrlRequestonUrlChange

    那么,当 URL 更改时,它是如何与您的应用程序通信的呢?它是如何实现的?

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

    尤其是 Key 不透明类型中包含的内容:

    var key = function() { key.__sendToApp(onUrlChange(_Browser_getUrl())); };
    

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

    _Browser_window.addEventListener('popstate', key);
    _Browser_window.addEventListener('hashchange', key);
    

    而且网址更改函数也调用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}?上面的代码 (_Browser_window.addEventListener('popstate', key)) 不是已经在 URL 发生变化时调用了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.application 初始化中的_Browser_window.addEventListener('popstate', key) 行就可以逃脱。但是当 URL 从 Javascript 更改时,该事件永远不会发出,因此他们需要一种方法来直接在这些函数中调用 app.onUrlChange(),也就是 key()

    当然,它还有一个额外的好处,就是将 URL API 的范围限定为仅使用 Browser.application 创建的应用程序。有点漫不经心的答案,但我没有时间写一个更短的答案。 ;)

    【讨论】:

      猜你喜欢
      • 2022-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-05
      • 1970-01-01
      相关资源
      最近更新 更多