用了这个浏览器功能,前端页面直接崩溃了,咋搞啊?

系统 浏览器
你是否遇到过这样的场景:在浏览器中使用谷歌翻译功能后,网页突然崩了,控制台错误:这一切的罪魁祸首,其实是谷歌翻译悄悄修改了你的页面结构!下面就来简单解释原因和解决方案。

你是否遇到过这样的场景:在浏览器中使用谷歌翻译功能后,网页突然崩了,控制台错误:

图片

这一切的罪魁祸首,其实是谷歌翻译悄悄修改了你的页面结构!下面就来简单解释原因和解决方案。

谷歌翻译如何“搞破坏”?

我们先看看谷歌翻译是如何工作的。

下面是未翻译的文字的 HTML 结构:

图片

翻译之后文字的 HTML 结构是这样的:

图片

翻译引擎将纯文本节点包裹在<font>标签中,这种看似无害的操作,却为现代前端框架埋下了定时炸弹。

两大致命场景

场景1:状态更新失效

对于像React这样的现代前端框架,它们依赖虚拟DOM来提高性能。当组件的状态或属性发生变化时,React会基于虚拟DOM的状态来操作真实DOM。然而,当真实DOM被谷歌翻译修改后,原节点的位置和状态与React的预期不一致,导致更新操作无法执行,页面因此无法正确更新。

例如,在以下计数器组件中:

import React, { useState } from"react";

const Counter = () => {
const [count, setCount] = useState(0);

const increment = () => {
    setCount(count + 1);
  };

const decrement = () => {
    setCount(count - 1);
  };

return (
    <div>
      <h1>example</h1>
      <p>count:{count}</p>
      <p>{count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
    </div>
  );
};

exportdefault Counter;

在这段代码中,两种显示方式在操作时的结果完全不同:

可以看到,使用<p>count:{count}</p>显示时,当页面使用翻译功能后,点击按钮将不会再更新,而<p>{count}</p>在使用谷歌翻译前后都是正常更新。

  • 对于第一种情况:谷歌翻译将原始文本拆分为多个嵌套的 <font> 节点,破坏了 React 原本控制的文本结构。当 count 更新时,React 尝试直接修改原始文本节点的内容,但此时该节点已被替换为 <font> 节点,导致更新失效。
  • 对于第二种情况:即使谷歌翻译包裹了 <font> 标签,但 整个 <p> 的唯一子节点仍然是动态值 {count} 对应的 <font>。React 在更新时可以通过对比虚拟 DOM 发现 <font> 内部的文本变化,从而正确更新内容。

场景2:应用崩溃

谷歌翻译的干扰还可能导致应用崩溃。当应用试图从DOM中移除一个已被谷歌翻译修改的文本节点时,会抛出一个NotFoundError错误。这是因为当应用试图从 DOM 中移除一个条件渲染的文本节点时,这个节点已被谷歌翻译卸载。

下面来看一个例子:

import React, { useState } from "react";

const ToggleText = () => {
  const [showText, setShowText] = useState(true);

  return (
    <div>
      <button onClick={() => setShowText(!showText)}>切换文本</button>
      {showText && "Hello, World!"}
    </div>
  );
};

export default ToggleText;

翻译后的文本被<font>标签包裹后,不再是父元素的直接子节点。当状态切换触发DOM卸载时,React会因找不到原始节点而抛出NotFoundError,最终导致组件树崩溃。

如何解决?

尽管这个问题在 React 社区中早已被提出,但官方至今都没有提供完美的解决方案。Dan 给出了一个方法来修复,但是会牺牲一定的性能,需要开发者根据实际情况来权衡是否有必要添加这段代码,并且这段代码也并没有解决本质问题。

https://github.com/facebook/react/issues/11538

图片图片

其实,对于上面提到的例子,只需要添加标签来分离文本和动态内容,这样 React 就不会直接删除和插入文本节点,就可以避免这个问题。但这只是其中一种情况,我们很难避开所有导致应用崩溃的情况。

有以下解决方案可供参考:

  • 阻止部分翻译 :可以通过给需要保持原样的部分添加 notranslate 属性来防止谷歌翻译对其进行操作。
<p translate="no"></p>
  • 完全禁用翻译 :如果希望整个页面都不被谷歌翻译,可以在 HTML 头部加入以下meta标签:
<meta name="google" cnotallow="notranslate">
  • 使用 Error Boundary 隔离错误: 对每个组件使用 Error Boundary,防止错误扩散到整个应用,导致应用崩溃。
<ErrorBoundary>
  <ToggleText />
</ErrorBoundary>
  • 必要时进行国际化:如果应用需要支持多种语言,可以考虑实现应用的多语言支持,而不是依赖谷歌翻译。这样可以更好地控制文本的显示和更新,告别第三方翻译插件的 DOM 污染。
责任编辑:武晓燕 来源: 前端充电宝
相关推荐

2021-08-28 06:15:49

浏览器手机浏览器夸克

2020-12-17 11:08:20

Safari手机浏览器苹果

2023-03-01 14:08:10

2021-10-11 10:22:43

AndroidChrome浏览器

2021-06-01 09:12:47

前端浏览器缓存

2011-05-06 09:36:16

动态页面

2021-05-17 14:15:16

Edge浏览器Android翻译功能

2021-09-05 15:55:05

WebP图片格式浏览器

2021-05-26 05:44:39

Google浏览器崩溃Chrome

2023-10-30 23:14:57

浏览器URL网页

2012-02-01 13:42:19

2021-01-19 16:02:16

Edge浏览器Chrome谷歌

2018-01-19 14:39:53

浏览器页面优化

2012-09-06 10:05:03

Windows 8浏览器

2011-02-23 10:57:27

Konqueror

2011-08-05 10:17:02

Chrome浏览器

2021-09-11 15:31:31

MozillaFirefoxTab Unloadi

2011-09-15 16:33:25

2023-12-19 22:48:22

2012-03-20 11:07:08

点赞
收藏

51CTO技术栈公众号