0

我正在尝试将 amp-analytics 脚本放入从 Next.js 生成的 amp 页面中,但由于 & 字符,SetInnerHTML 很危险地破坏了 JSON 配置。

这是代码:

<amp-analytics id='analytics1' type='googleanalytics'>
  <script type='application/json' dangerouslySetInnerHTML={{ __html: `
    {
      "vars": {
        "account": "XX-XXXXXXXX-X"
      },
      "requests": {
         "experiment": "\${pageview}&xid=\${xid}&xvar=\${xvar}"
      }
    }
  ` }} />
</amp-analytics>

结果如下: 在此处输入图像描述

如您所见,& 字符已转换为 \u0026,现在 amp-analytics 标记不起作用。

我也试过这个:

<amp-analytics id='analytics1' type='googleanalytics'>
  <script type='application/json' dangerouslySetInnerHTML={{ __html: `
    {
      "vars": {
        "account": "XX-XXXXXXXX-X"
      },
      "requests": {
         "experiment": "${JSON.stringify('${pageview}&xid=${xid}&xvar=${xvar}')}"
      }
    }
  ` }} />
</amp-analytics>

但是得到了无效的 JSON(带有正确的 & 符号) 在此处输入图像描述

关于如何解决这个问题的任何想法?

事实证明,这是因为 Next.js 中的 AMP 优化器而发生的——github.com/ampproject/amp-toolbox/pull/649 现在我必须为这种情况找到解决方案

4

1 回答 1

0

您不需要使用dangerouslySetInnerHTML,因为您要做的就是设置文本内容。dangerouslySetInnerHTML仅当您需要将 HTML 解析为 DOM 节点时才需要。

您可以像这样设置文本内容:

<script type='application/json'>
  {JSON.stringify(
    {
      vars: {
        account: 'XX-XXXXXXXX-X',
      },
      requests: {
        experiment: `${pageview}&xid=${xid}&xvar=${xvar}`,
      },
    }
  )}
</script>

如果你这样做,React 足够聪明,知道标签中不需要 HTML 实体script,所以那些&s 不会被转义(不像它是一个普通的 HTML 元素,比如div)。

您可以像这样验证(演示):

const InnerHtmlLogger = ({ TagName }) => {
  const ref = useRef(null);

  useEffect(() => {
    console.log(TagName, ref.current.innerHTML);
  }, [TagName]);

  return (
    <TagName ref={ref}>
      {JSON.stringify({
        '&': '&&',
        '&&&': ['&&&&', '&&&&&']
      })}
    </TagName>
  );
};

const App = () => {
  return (
    <>
      <InnerHtmlLogger TagName='div' />
      <InnerHtmlLogger TagName='script' />
    </>
  );
}

// Log output:
// div {"&amp;":"&amp;&amp;","&amp;&amp;&amp;":["&amp;&amp;&amp;&amp;","&amp;&amp;&amp;&amp;&amp;"]}
// script {"&":"&&","&&&":["&&&&","&&&&&"]}
于 2020-08-17T14:04:47.310 回答