如何为每次加载页面时运行的gatsby页面添加脚本?

时间:2020-08-06 17:01:03

标签: javascript reactjs dom gatsby

我正在尝试向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的功能破坏或破坏了,或者我没有正确使用它。任何帮助将不胜感激。

3 个答案:

答案 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所说,这是一种解决方法,但是我的网站很小,到目前为止,我还没有注意到对性能的任何严重损害,但是如果需要的话,我稍后会重建脚本。