无法使用NextJS实现Materialize-CSS初始化脚本

问题描述 投票:1回答:1

我正在使用Materialize CSS来设计我正在处理的网络应用程序。我正在使用NextJS和ReactJS构建应用程序。我已经使用Materialize CSS文件中定义的类设置了导航栏的样式。但是,我无法使用规定的初始化脚本as instructed on the Materialize website实现响应侧边栏功能。

我的Navbar组件(./components/Navbar.js)如下所示:

import React, { Component, Fragment } from 'react';
import Link from 'next/link';
import $ from 'jquery';

class Navbar extends Component {
  constructor(props) {
    super(props)
    this.props = props;
  }

  componentDidMount = () => {
    document.addEventListener('DOMContentLoaded', function() {
      var elems = document.querySelectorAll('.sidenav');
      var instances = M.Sidenav.init(elems, options);
    });
  }

  render() {
    return (

      <Fragment>
        <nav>
          <div className="nav-wrapper blue">
            <Link prefetch href='/'>
              <a href="/" className="brand-logo">Project Coco</a>
            </Link>
            <a href="#" data-target="slide-out" className="sidenav-trigger"><i className="material-icons">menu</i></a>
            <ul id="nav-mobile" className="right hide-on-med-and-down">
              <li>
                <Link prefetch href='/'>
                  <a>Home</a>
                </Link>
              </li>
              <li>
                <Link prefetch href='/about'>
                  <a>About</a>
                </Link>
              </li>
              <li>
              </li>
            </ul>
          </div>
        </nav>
        {/* Sidenav markup */}
        <ul className="sidenav" id="slide-out">
          <li>
            <Link prefetch href='/'>
              <a>Home</a>
            </Link>
          </li>
          <li>
            <Link prefetch href='/about'>
              <a>About</a>
            </Link>
          </li>
        </ul>
      </Fragment>
    );
  }
}

export default Navbar;

很明显,这个功能(侧边栏)需要JQuery。所以我已经通过yarn添加它并使用import $ from 'jquery'调用它。但是在运行时,它会抛出一个错误,说sidenav不是一个函数。

我甚至尝试完全取消使用JQuery,只是在componentDidMount中使用初始化脚本的vanilla JS版本:

document.addEventListener('DOMContentLoaded', function() {
    var elems = document.querySelectorAll('.sidenav');
    var instances = M.Sidenav.init(elems, options);
  });

但这一次,虽然没有错误,但功能仍然拒绝工作,点击汉堡包菜单不会触发sidenav,它应该。

整个代码回购在Github上作为参考,原型应用程序在schandillia.com上运行。有解决方案吗

P.S。:问题似乎是ComponentDidMount中的初始化代码在MaterialiseCSS.js(被称为外部文件)之前执行,它依赖于它。围绕这一切的任何工作都可能是一个潜在的解决方案,尽管这只是一个假设。

materialize next.js
1个回答
3
投票

您需要将materialize-css导入到组件中。可悲的是,如果你试图做import 'materialize-css'你会得到一个window is undefined错误。这是因为Next.js是通用的,这意味着它首先在服务器端执行代码,其中window不存在。我用于此问题的解决方法如下:

如果你没有,请安装materialize-css:

$ npm i materialize-css

只有在定义了window时,才将materialize-css导入到您的组件中:

if (typeof window !== 'undefined') {
    window.$ = $;
    window.jQuery = $;
    require('materialize-css');
}

然后,在你的componentDidMount方法:

componentDidMount = () => {
    $('.sidenav').sidenav();
}

所以你的组件看起来像这样:

import React, { Component, Fragment } from 'react';
import Link from 'next/link';
import $ from 'jquery';

if (typeof window !== 'undefined') {
    window.$ = $;
    window.jQuery = $;
    require('materialize-css');
}

class Navbar extends Component {
    constructor(props) {
        super(props)
        this.props = props;
    }

    componentDidMount = () => {
        $('.sidenav').sidenav();
    }

    render() {
        return (
              <Fragment>
                <nav>
                    ...
                </nav>
                {/* Sidenav markup */}
                <ul className="sidenav" id="slide-out">
                    ...
                </ul>
              </Fragment>
        );
    }
}

export default Navbar;

资料来源:Next.js FAQthis issue

© www.soinside.com 2019 - 2024. All rights reserved.