TypeError:无法读取 null 的属性(读取“classList”)
Posted
技术标签:
【中文标题】TypeError:无法读取 null 的属性(读取“classList”)【英文标题】:TypeError: Cannot read properties of null (reading 'classList') 【发布时间】:2022-01-12 07:37:58 【问题描述】:我正在使用 nextjs 应用程序。我只是想制作一个下拉菜单。
这是我的完整代码:
import React from 'react'
import Link from 'next/link'
import styles from './header.module.css'
const Header = () =>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
const myFunction =()=>
document.getElementById(styles.myDropdown).classList.toggle("show");
// Close the dropdown menu if the user clicks outside of it
if (typeof window !== "undefined")
window.onclick = function (event)
if (!event.target.matches('.dropbtn'))
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++)
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show'))
openDropdown.classList.remove('show');
return (
<div className=styles.header>
<div className=styles.logoLink>
<img src="images/itacs.png" className=styles.logo />
</div>
<div className=styles.services>
<ul>
<li><Link href="/page">Docs</Link></li>
<li><Link href="/page">Learn</Link></li>
<li><Link href="/page">Projects</Link></li>
<li><Link href="/page">Blog</Link></li>
<div className=styles.dropdown>
<button onClick=myFunction className=styles.dropbtn>Dropdown</button>
<div id=styles.myDropdown className=styles.dropdownContent>
<a href="/">Link 1</a>
<a href="/">Link 2</a>
<a href="/">Link 3</a>
</div>
</div>
</ul>
</div>
<form action="" className=styles.headerForm>
<a href="/" className=styles.logIn>Log In</a>
<a href="/" className=styles.getStarted>Get Started</a>
</form>
</div>
)
export default Header
这里我刚刚在div的id中添加了classlist! 当按钮被单击为下拉菜单时,我试图显示下面的 div。 我无法弄清楚这一点!
对于任何想知道 css 文件中存在什么的人:
/* dropdown */
/* Dropdown Button */
.dropbtn
background-color: #3498DB;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
/* Dropdown button on hover & focus */
.dropbtn:hover, .dropbtn:focus
background-color: #2980B9;
/* The container <div> - needed to position the dropdown content */
.dropdown
position: relative;
display: inline-block;
/* Dropdown Content (Hidden by Default) */
.dropdownContent
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
/* Links inside the dropdown */
.dropdownContent a
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
/* Change color of dropdown links on hover */
.dropdownContent a:hover background-color: #ddd
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show display:block;
任何帮助将不胜感激!
【问题讨论】:
styles.dropdownContent
和 styles.myDropdown
设置在哪里?如果您使用变量在标记中设置 id 和 className,您可能应该在脚本中使用相同的变量,例如 document.getElementById($styles.myDropdown
).classList.toggle("show");
【参考方案1】:
应该是<div className="dropdown">
而不是<div class="dropdown">
和<div id=styles.myDropdown className=styles.dropdownContent>
你也应该避免在 react/next 应用中使用 vanilla js。
你会得到一个像这样的反应状态:
const [dropdownToggled, toggleDropdown] = useState(false);
const handleClick = () =>
toggleDropdown(!dropdownToggled);
;
并且有一个条件是你的 jsx 是否有一个 className hidden
设置 display: none
类似这样的:
<div
className=`$styles.dropdownContent
$dropdownToggled ? styles.hidden : ""`
>
<a href="/">Link 1</a>
<a href="/">Link 2</a>
<a href="/">Link 3</a>
</div>
要在用户在外部点击时关闭下拉菜单,您需要这样的 div:
<div
className=styles.backdrop
onClick=() => toggleDropdown(true)
></div>
样式如下:
.backdrop
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
现在,由于此 div 占据整个屏幕,并且当用户单击页面上的任何位置时绝对定位,所以 onClick 将触发并切换下拉菜单。
Working CodeSandbox.
【讨论】:
你是对的!我没有看到这一点,因为代码看起来像 html,而它不是 HTML,而是他妈的 JSX。感谢您指出!确保变量内容实际上与getElementById
和 getElementsByClassName
中的静态字符串匹配也是很好的,除了那些 vanilla JS DOM 函数可能不是“React 方式”的代码风格。
确实,我建议避免在 react/next 项目中做 vanilla js 的东西,你会改为按钮上的 onClick
道具并使用反应状态来知道下拉菜单何时是或不是切换。用一个例子更新了答案,你会怎么做
我添加了我的答案,非常感谢@whygee 的帮助!它有效,但需要进行一些配置!
@whygee 您的方法绝对有效,但我有一个小问题。当我单击按钮时,它会打开并保持打开状态,直到我再次单击它。当用户点击其他地方时,有什么方法可以关闭下拉菜单?
@ITACS 我想到的最简单的方法是添加一个虚拟的“背景” div,该 div 绝对定位并采用负 z-index 的整个页面宽度/高度,因此它始终位于背景和onClick,下拉状态被切换。用这种方法更新了 CodeSandbox【参考方案2】:
import React, useState from 'react'
import Link from 'next/link'
import styles from './header.module.css'
const Header = () =>
const [dropdownToggled, toggleDropdown] = useState(false);
const handleClick = () =>
toggleDropdown(!dropdownToggled);
console.log("boy");
;
// Close the dropdown menu if the user clicks outside of it
if (typeof window !== "undefined")
window.onclick = function (event)
if (!event.target.matches('#dropbtn'))
var dropdowns = document.getElementsByClassName(styles.dropdownContent);
var i;
for (i = 0; i < dropdowns.length; i++)
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show'))
openDropdown.classList.remove('show');
return (
<div className=styles.header>
<div className=styles.logoLink>
<img src="images/itacs.png" className=styles.logo />
</div>
<div className=styles.services>
<ul>
<li><Link href="/page">Docs</Link></li>
<li><Link href="/page">Learn</Link></li>
<li><Link href="/page">Projects</Link></li>
<li><Link href="/page">Blog</Link></li>
<div className=styles.dropdown>
<button onClick=handleClick id="dropbtn" className=styles.dropbtn>Dropdown</button>
<div
className=`$styles.dropdownContent $dropdownToggled ? styles.show : ""`
>
<a href="/">Link 1</a>
<a href="/">Link 2</a>
<a href="/">Link 3</a>
</div>
</div>
</ul>
</div>
<form action="" className=styles.headerForm>
<a href="/" className=styles.logIn>Log In</a>
<a href="/" className=styles.getStarted>Get Started</a>
</form>
</div>
)
export default Header
是的,终于配置好了。感谢whygee 和Ingo Steinkie
【讨论】:
【参考方案3】:如果您使用变量在标记中设置 id 和 className,您可能应该在脚本中使用相同的变量,例如
document.getElementById(`$styles.myDropdown`).classList.toggle("show");
[编辑]或没有不必要的冗余模板字符串:
document.getElementById(styles.myDropdown).classList.toggle("show");
假设styles.myDropdown
是一个字符串(不是一个对象)。
否则您的代码无法确保id
和className
相同。
【讨论】:
我试过了,但它不起作用。它仍然给我同样的错误,下一个 js 在 myFunction 的右括号中指出错误:第 10 行。应该怎么做? 第 10 行是哪一行? document.getElementById 行后的右花括号? 还看到我的(快速输入的)答案使用了不必要的模板字符串,较短的版本应该是document.getElementById(styles.myDropdown)
,但无论如何这不应该有任何区别。
styles.myDropdown
的值和类型是什么?这应该是一个字符串。目前我只能猜测,因为我还没有看到 header.module.css
的内容,但我怀疑这会从 CSS 文件中返回一个字符串?
@IngoSteinkie 我也会添加我的错误和 css 文件...以上是关于TypeError:无法读取 null 的属性(读取“classList”)的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:无法读取 null 的属性(读取“classList”)
TypeError:无法读取 null 的属性(读取“1”)
TypeError:无法读取 null 的属性“userID”