如何存储/存储JavaScript事件并在以后重用它?

Lim*_*nte 14 javascript events local-storage web-storage

来自https://developers.google.com/web/fundamentals/app-install-banners/#trigger-m68

let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
  e.preventDefault();
  // Stash the event so it can be triggered later.
  deferredPrompt = e;
});
Run Code Online (Sandbox Code Playgroud)

这段代码很好,但我想稍后在另一个地方触发藏匿事件.为了执行该操作,我需要将事件存储在变量中,而不是存储在其他地方.

问题:如何使用其方法存储事件?

我尝试使用对象的序列化/反序列化进行本地存储:

> localStorage.setItem('stashed-event', JSON.stringify(e))
>
> JSON.parse(localStorage.getItem('stashed-event'))
Run Code Online (Sandbox Code Playgroud)

但是这种方法不能按预期工作,因为它只存储键值并丢失所有事件方法.

Jos*_*osh 9

您无法以这种方式存储活动.您想要存储一个对象.只有可序列化的属性才能存储在这样的对象中.函数在JavaScript中不可序列化.函数不能在许多语言中序列化.

从根本上说,这基本上是因为当您反序列化对象时,其签名可能会发生变化.如果您曾在java中编程,则在读取序列化对象并尝试重建对象时,这类似于反序列化错误.因为对象的方法函数的主体可以在将对象写入某个存储器然后稍后读取之间进行更改,所以方法不可序列化.这是因为在序列化对象时,它不会序列化定义方法的接口定义.它只存储数据.

序列化为json字符串的原因相同,它会丢弃函数.

不是存储事件,而是将事件中的有用信息存储在对象中(或者让stringify隐式删除并直接使用事件).

您使用哪种存储方法取决于您的问题中未提及的内容.例如应该存储多长时间,是否应该在您网站的原点之外提供,通常存储多少数据,是否存储多个对象等等.根据您问题中提供的有限信息,你可能只使用localStorage或内存数组.

如果您发现需要存储数百个对象,那么indexedDB将开始更合适.但是,只选择不同的存储介质对于是否可以存储功能没有任何影响.您无法存储功能.


Sau*_*pal 8

一旦I/O 2018提到有关A2HS事件的处理是从现在开始驱动的开发人员,就有很多关于此的讨论.这也是在官方文档中捕获并从中受到启发,有一篇精美的文章详细解释了如何实现这种情况.虽然我建议通过完整的文章来正确理解A2HS流程的更新动态,但请随意跳转到"新添加到主屏幕流程"部分以满足您的要求.

简而言之,请按照以下步骤操作:

  1. beforeinstallprompt事件处理程序范围之外创建一个变量.
  2. beforeinstallprompt在上面的处理程序中保存对事件对象的引用.
  3. 稍后使用此按钮可根据需要触发添加到主屏幕提示.

本文有完整的代码片段,您可以参考/重用.

编辑:我再次阅读你的问题,并意识到你可能会特别寻找的一个重要方面,即"在其他地方"使用它.如果这意味着你指的是在不同的页面上使用它,那么我的建议是将事件对象存储在:

  1. IndexedDB是"对象存储"的集合,您可以将对象放入其中.缺点 - 可能具有浏览器兼容性限制.此外,可能导致大量嵌套回调.
  2. 或者您可以选择使用"进程内缓存"(应用程序的堆内存),这也不需要序列化.缺点 - 但这不能在多个服务器之间共享.

除此之外,我现在无法预见到免费解决方案.但是会尝试解决它并可能更新线程.


luc*_*chi 5

读了几遍你的问题和另外一些答案后,

\n\n

问题:任何 javascript 对象如何与其方法一起存储?

\n\n

答案是:没有办法。

\n\n

然而,

\n\n

乔什正确地解释了您可以从事件中提取并存储所有可序列化的属性,例如数据。

\n\n

我只是补充一下,您可以稍后在任何地方使用相同的数据创建一个事件,这个新事件将具有任何事件具有的所有方法,但现在可能没有用。

\n\n

显然,即使在数据中序列化,诸如timeStampisTrusted等属性也会在创建新事件时被覆盖。

\n\n

您只是错过/需要的是EventTarget ,即event.target属性的值,\n当 document.body 永久卸载或序列化事件对象时,该引用将永远丢失。

\n\n

但是,如果它仍然存在,或者如果您知道 event.target 应该是什么,例如 DOM 元素或您可以引用的任何对象,从您重新创建事件的任何位置(在哪里?),只需将您的事件分派到该对象,如果它监听该event.type,\n您的全新事件至少应该被听到。

\n\n

来自 MDN EventTarget的简单示例,或参见EventTarget.dispatchEvent

\n\n

作为对cegfault广泛答案的评论:eval和文本源代码...可能是<script>文本源代码</script> ...如果您的脚本生成一个(字符串)脚本。如果不是,你 \xc2\xb4d 可能最好进一步回溯到你的脚本在哪里创建了出现在你的事件中的不可序列化的东西,并考虑重新创建这些东西,而不是事件。

\n