防止我的 Elm 应用程序在第 3 方更改 DOM 时崩溃

Posted

技术标签:

【中文标题】防止我的 Elm 应用程序在第 3 方更改 DOM 时崩溃【英文标题】:Prevent my Elm app from crashing when a 3rd party changes the DOM 【发布时间】:2020-12-24 08:13:49 【问题描述】:

我有一个 Elm 应用程序。不久前,当我使用 FontAwesome 图标时,我意识到我的应用程序在本地崩溃了。我开始明白这是因为我选择了 SVG 图标,因此 FontAwesome 正在修改 DOM。这与 Elm 的 VDOM 机制相冲突。

这很容易解决——我迁移到了使用伪元素的 CSS 版本的 FontAwesome。最近一些用户抱怨生产中的应用程序冻结,他们显示了与我的日志数据不匹配的状态截图。过了一段时间,我才意识到所有这些用户都有谷歌翻译自动为他们翻译页面。 Google Translate clearly alters the DOM,所以 Elm 崩溃我并不感到惊讶。

如何防止我的 Elm 应用崩溃?如果第 3 方更改 DOM,有没有办法得到通知?这样我什至可以通知用户他们有一个干扰应用程序的扩展程序。

【问题讨论】:

我的直接想法是看看 React github.com/facebook/react/issues/11538 会发生什么 感谢@SimonH,提供有用的资源。 关注了该线程,React's fix was not to React itself but to the reactjs.org website。一个explanation here. 我用同样的问题创建了this issue。 【参考方案1】:

看看这里 - How we made Elm and Google Translate work together。

他们的方法是使用下面的函数劫持 Elm 在 dom 更新期间调用的 Elm replaceData 方法。你可以在让 Elm 控制 dom 之前运行它。

htmlFontElement.prototype.replaceData =
  function replaceData(_0, _1, string) 
    this.parentNode.replaceChild(
      document.createTextNode(string),
      this
    );
  ;

显然,“Google 翻译将 DOM 中的每个文本节点替换为包含至少一个标签的标签 - 每个句子一个标签”。例如:

<span>Insurello. Rätt ersättning till alla</span>

被翻译成

&lt;span&gt;&lt;font&gt;&lt;font&gt;Insurello. &lt;/font&gt;&lt;font&gt;The right compensation for everyone&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;

此方法可避免尝试编辑跨度,而是将其替换为新跨度。添加节点后,Google 翻译将翻译该文本。

【讨论】:

谢谢!我刚刚在 Elm 时事通讯中也遇到过这个问题,它确实适用于 Google 翻译。【参考方案2】:

此问题与 Elm 中的 Google Maps 或 Google Places Autocomplete 的问题密切相关。我过去使用的解决方案是提供一个没有子元素的 div,其 id 可以从 javascript 中指向。

因为 div 没有子元素,所以 Elm 不会在后台检查它是否在内部发生了变化。

查看此blog post 或谷歌“榆树地图”以获取有关如何执行此操作的说明

-- 编辑-- 我已经更好地阅读了这个问题,这可能不适用于谷歌翻译问题,因为它会更改整个 DOM 中的所有文本。我将把它留在这里,以防问题带来更多的人,他们在第 3 方更改 DOM 时会遇到更多常见问题

【讨论】:

【参考方案3】:

我遇到了和你一样的问题,并通过迁移到 Elm-FontAwesome 库来解决它。基本上你所要做的就是替换这个语法:

i [ Svga.class "fas fa-check" ] []

用这个:

Icon.viewIcon Icon.check

您可以查看示例项目以了解更多详细信息:https://github.com/Lattyware/elm-fontawesome-example

【讨论】:

嗨!欢迎来到 SO!是的,这听起来是让 Elm 和 FontAwesome SVG 图标一起工作的另一种方式,但我真正感兴趣的是如何处理这类问题。【参考方案4】:

我不知道如何防止崩溃,但我认为您应该能够使用 current mutation observer API 注册对 DOM 的更改。

在此之前有几个 deprecated mutation events 像 DOMSubtreeModified 也可以提供帮助,但它们已被弃用。

【讨论】:

这将通知您所有更改,包括 Elm 本身修改 DOM,而不仅仅是第 3 方所做的更改。除非您能以某种方式过滤掉 Elm 所做的更改,否则这是行不通的。

以上是关于防止我的 Elm 应用程序在第 3 方更改 DOM 时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

我的 javascript 和移植的 elm 之间的 UI 滞后

使用 Elm.Browser.Dom 按类名获取元素

iOS 无法在第一页加载时操作 jQuery DOM 更改

第 3 方 Jar 退出我的程序?

如何防止其他用户更改 gps 位置和位置更新调用每个小间隔(比如 3 秒)

如何在 Elm 中设置焦点?