我正在尝试向Gatsby中的单个页面添加自定义砌体脚本。它修改了网格布局中<div>
元素的样式属性,但是从本质上讲,每次页面加载或调整大小时,脚本都需要执行此操作。
我试图完成此任务的方法是通过要求脚本返回函数以返回React组件:
// in 'page.js'
export default () => {
useEffect(() => {
require('./scripts/masonry');
}
return // blah blah blah...
}
在脚本中,我将需要脚本执行的所有操作都放在了名为resizeAll
的函数中,并将其附加到window.onloadend
上,并将其添加到调整大小的事件侦听器中:>
// in the masonry script at the very bottom
window.onloadend = resizeAll;
window.addEventListener('resize', resizeAll);
但是这不起作用,因为该脚本似乎仅在调整页面大小时才运行,而在加载或导航到页面时却不运行。我怀疑window.onloadend
由于某种原因被gatsby的功能破坏或破坏了,或者我没有正确使用它。任何帮助将不胜感激。
答案 0 :(得分:1)
您可以使用 React Helmet (反应头盔)完成此操作,该操作基本上是将内容写入html页面<head>
标签。另外,您将需要Gatsby的withPrefix
来解析Gatsby内置脚本的路径。
您正在使用的大多数盖茨比启动器已经设置了反应头盔(请查看您的package.json
)。如果是这种情况,只需将脚本放入项目的/static/
文件夹中,然后在React中像下面这样将脚本放入页面的<head>
中:
import Helmet from "react-helmet";
import { withPrefix } from "gatsby";
<Helmet>
<script src={withPrefix('masonry.js')} />
</Helmet>
如果由于某种原因您的Gatsby项目尚未设置React Helmet,则可以按照说明here进行设置。
答案 1 :(得分:0)
最简单,最干净的方法是使用gatsby-browser.js
。 Gatsby在那里提供了几种API,onClientEntry
可以满足您的要求。从文档中:
onClientEntry
功能
(_: emptyArg, pluginOptions: pluginOptions) => undefined
在Gatsby浏览器运行时首次启动时调用。
因此,根据您的代码,在您的gatsby-browser.js
中添加:
export const onClientEntry = () => {
useEffect(() => {
require('./scripts/masonry');
}, [])
};
上面的代码假定:
如果上述方法无法按预期运行,或者您不希望在所有地方使用它。我会尝试在原始[]
钩子上添加一个空的deps(useEffect
),因为这是最接近componentDidMount
生命周期的解决方法:
useEffect(() => {
require('./scripts/masonry');
}, [])
如果脚本是外部的(第三方):
useEffect(() => {
const script = document.createElement('script')
script.async = true script.defer = true
script.src = 'https://your_script.com'
document.querySelector('ANY_UNIQUE_DIV').appendChild(script)
}, [])
上面的代码只是一个初步的解决方法,在任何React应用程序中都应避免使用document
和其他DOM变量,因为它们对浏览器的性能有很大的影响,您可以使用useRef
钩子。
答案 2 :(得分:0)
原来我解决了这个问题!挂钩似乎并没有解决问题,所以我将resizeAll
函数插入了gatsby-browser
的onRouteUpdate导出中。
就像Ferran Buireu所说,这是一种解决方法,但是我的网站很小,到目前为止,我还没有注意到对性能的任何严重损害,但是如果需要的话,我稍后会重建脚本。