我正在使用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-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 FAQ和this issue。