问题描述
我试图将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>
关于如何解决此问题的任何想法?
事实证明,发生这种情况的原因是Next.js中的AMP Optimizer — github.com/ampproject/amp-toolBox/pull/649现在,我必须找到这种情况的解决方案
解决方法
您无需使用dangerouslySetInnerHTML
,因为您只需要设置文本内容即可。仅在需要将HTML解析为DOM节点时才需要dangerouslySetInnerHTML
。
您可以这样设置文本内容:
<script type='application/json'>
{JSON.stringify(
{
vars: {
account: 'XX-XXXXXXXX-X',},requests: {
experiment: `${pageview}&xid=${xid}&xvar=${xvar}`,}
)}
</script>
如果您采用这种方式,React足够聪明,可以知道script
标记中不需要HTML实体,因此这些&
不会被转义(除非它是一个普通的HTML元素,例如div
)。
您可以像这样(demo)进行验证:
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 {"&":"&&","&&&":["&&&&","&&&&&"]}
// script {"&":"&&","&&&":["&&&&","&&&&&"]}