(Gatsby) 在我刷新页面之前,Datawrapper iframe 没有显示
(Gatsby) Datawrapper iframes aren't displaying before I've refreshed the page
我正在使用 Datawrapper 在我的网站上将图表显示为 iframe。
我最近刚从 Remark 迁移到 MDX。使用新设置后,我的 Datawrapper 图表不会在允许以“传统”方式加载包含图表的页面之前加载(即点击刷新或直接关注包含图表的页面)。
因此,如果您遵循此 link,图表显示良好:kolstadmagnus.no/ekspert-mener-a-ha-svaret-bak-krfs-stortingssmell。
但是,如果您转到主页 (kolstadmagnus.no),然后点击 link(第二顶 post),图表将不会显示。
一些上下文
Datawrapper iframe 使用此脚本,以便 iframe 响应:
!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();
由于 Gatsby 按照它的方式工作(不是“传统地”加载每个页面——抱歉,我不知道这个功能叫什么),我不得不把这个脚本放在 html.js 文件中,像这样:
<body {...props.bodyAttributes}>
{props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: props.body }}
/>
{props.postBodyComponents}
<script
dangerouslySetInnerHTML={{
__html: `
!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}(); `
}}
/>
</body>;
这会导致脚本针对整个网站执行,而不仅仅是针对单个页面执行,从而解决了在使用 iframe 进入页面后需要点击刷新的问题。
虽然使用 MDX,问题又回来了。但是现在iframe根本不显示了。
我该如何解决这个问题?
Gatsby 从 @reach/router
扩展了它的导航和它的“加载页面”,所以从 React。
我非常不鼓励在 html.js
的某些页面中嵌入需要呈现的自定义脚本,因为正如您指出的那样,它将在全球范围内加载。您可以通过 运行 在本地或雾化它来实现相同的效果。
您面临的问题是脚本直接指向 DOM(因为使用了 window.addEventListener
),而在 React 中(因此使用 Gatsby)您创建并操作了一个虚拟DOM (vDOM)。播放和操纵两者可能会导致误导行为,因为一个人不知道另一个人何时发生变化,反之亦然,从而破坏水合作用和再水化过程(这就是为什么你在刷新时看到结果:因为水合作用永远不会发生)。
也就是说,理想的解决方案是使用基于 React 的 Datawrapper 模块,例如 react-datawrapper-chart
或使用其他自定义解决方案。使脚本响应不是什么大事,您可以使用基于 React 的代码进行相同的计算。
或者,按照您的“工作”方法,您可以使用特定页面上的 Helmet
组件加载自定义脚本:
const SomeSpecificPage = () =>{
return <>
<Helmet>
<script
dangerouslySetInnerHTML={{
__html: `
!function(){"use strict";window.addEventListener("message",
(function(e){if(void 0!==e.data["datawrapper-height"]){var
t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}(); `
}}
/>
</Helmet>
</>
}
我正在使用 Datawrapper 在我的网站上将图表显示为 iframe。
我最近刚从 Remark 迁移到 MDX。使用新设置后,我的 Datawrapper 图表不会在允许以“传统”方式加载包含图表的页面之前加载(即点击刷新或直接关注包含图表的页面)。
因此,如果您遵循此 link,图表显示良好:kolstadmagnus.no/ekspert-mener-a-ha-svaret-bak-krfs-stortingssmell。
但是,如果您转到主页 (kolstadmagnus.no),然后点击 link(第二顶 post),图表将不会显示。
一些上下文
Datawrapper iframe 使用此脚本,以便 iframe 响应:
!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();
由于 Gatsby 按照它的方式工作(不是“传统地”加载每个页面——抱歉,我不知道这个功能叫什么),我不得不把这个脚本放在 html.js 文件中,像这样:
<body {...props.bodyAttributes}>
{props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: props.body }}
/>
{props.postBodyComponents}
<script
dangerouslySetInnerHTML={{
__html: `
!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}(); `
}}
/>
</body>;
这会导致脚本针对整个网站执行,而不仅仅是针对单个页面执行,从而解决了在使用 iframe 进入页面后需要点击刷新的问题。
虽然使用 MDX,问题又回来了。但是现在iframe根本不显示了。
我该如何解决这个问题?
Gatsby 从 @reach/router
扩展了它的导航和它的“加载页面”,所以从 React。
我非常不鼓励在 html.js
的某些页面中嵌入需要呈现的自定义脚本,因为正如您指出的那样,它将在全球范围内加载。您可以通过 运行 在本地或雾化它来实现相同的效果。
您面临的问题是脚本直接指向 DOM(因为使用了 window.addEventListener
),而在 React 中(因此使用 Gatsby)您创建并操作了一个虚拟DOM (vDOM)。播放和操纵两者可能会导致误导行为,因为一个人不知道另一个人何时发生变化,反之亦然,从而破坏水合作用和再水化过程(这就是为什么你在刷新时看到结果:因为水合作用永远不会发生)。
也就是说,理想的解决方案是使用基于 React 的 Datawrapper 模块,例如 react-datawrapper-chart
或使用其他自定义解决方案。使脚本响应不是什么大事,您可以使用基于 React 的代码进行相同的计算。
或者,按照您的“工作”方法,您可以使用特定页面上的 Helmet
组件加载自定义脚本:
const SomeSpecificPage = () =>{
return <>
<Helmet>
<script
dangerouslySetInnerHTML={{
__html: `
!function(){"use strict";window.addEventListener("message",
(function(e){if(void 0!==e.data["datawrapper-height"]){var
t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}(); `
}}
/>
</Helmet>
</>
}