我正试图用新框架创建一个网站,特别是我试图在导航栏中放置一个按钮的简单下拉功能,但我不知道该把代码放在哪里。我尝试在index.tsx文件中创建一个类并在export default function Home()中初始化它,但是我得到的唯一东西是一个ReferenceError,因为document没有定义。
index.tsx
/** @jsx h */
import { h } from "preact";
import HeaderWithLogin from "../islands/HeaderWithLogin.tsx";
import Navbar from "../islands/Navbar.tsx";
class Dropdown {
private _targetElement: Element | null;
private _triggerElement: Element | null;
private _visible: boolean;
constructor(
targetElement: Element | null = null,
triggerElement: Element | null = null
) {
this._targetElement = targetElement;
this._triggerElement = triggerElement;
this._visible = false;
this._init();
}
_init() {
if (this._triggerElement) {
this._triggerElement.addEventListener("click", () => {
this.toggle();
});
}
}
_handleClickOutside(ev: MouseEvent) {
const clickedE = ev.target as Element;
if (
clickedE !== this._targetElement &&
!(this._targetElement as Element).contains(clickedE) &&
!this._triggerElement?.contains(clickedE) &&
this._visible
) {
this.hide();
}
document.body.removeEventListener(
"click",
this._handleClickOutside,
true
);
}
toggle() {
if (this._visible) {
this.hide();
document.body.removeEventListener(
"click",
this._handleClickOutside,
true
);
} else {
this.show();
}
}
show() {
this._targetElement?.classList.remove("hidden");
this._targetElement?.classList.add("block");
document.body.addEventListener("click", this._handleClickOutside, true);
this._visible = true;
}
hide() {
this._targetElement?.classList.remove("block");
this._targetElement?.classList.add("hidden");
this._visible = false;
}
}
function initDropdown() {
document
.querySelectorAll("[data-dropdown-toggle]")
.forEach((triggerElement) => {
const targetElement: Element | null = document.getElementById(
triggerElement.getAttribute("data-dropdown-toggle") as string
);
new Dropdown(targetElement, triggerElement);
});
}
export default function Home() {
if (document.readyState !== 'loading') {
initDropdown();
} else {
document.addEventListener('DOMContentLoaded', initDropdown);
}
return (
<body>
<Navbar></Navbar>
</body>
);
}Navbar.tsx
/** @jsx h */
import { h } from "preact";
import { tw } from "@twind";
export default function Navbar() {
return (
<nav>
<ul>
<li>
<button data-dropdown-toggle="dropdownElement">Dropdown Element</button>
<div id="dropdownElement">
<ul>
<li>
<a href="/">Link To Other Page</a>
</li>
</ul>
</div>
</li>
<li>
<button>Button 1</button>
</li>
<li>
<a href="/">Button 2</a>
</li>
<li>
<a href="/">Button 3</a>
</li>
</ul>
<div>
<input type="text" id="search-navbar" class={tw`block p-2 pl-10 w-full text-gray-900 bg-gray-50 rounded-lg border border-gray-300 sm:text-sm focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500`} placeholder="Search..."></input>
</div>
</nav>
);
}错误:
An error occured during route handling or page rendering.
ReferenceError: document is not defined
at Object.Home (file:///.../routes/index.tsx:89:5)
at h (https://esm.sh/v87/preact-render-to-string@5.2.0/X-ZC9wcmVhY3RAMTAuOC4y/deno/preact-render-to-string.js:4:1003)
at h (https://esm.sh/v87/preact-render-to-string@5.2.0/X-ZC9wcmVhY3RAMTAuOC4y/deno/preact-render-to-string.js:4:1103)
at h (https://esm.sh/v87/preact-render-to-string@5.2.0/X-ZC9wcmVhY3RAMTAuOC4y/deno/preact-render-to-string.js:4:1103)
at h (https://esm.sh/v87/preact-render-to-string@5.2.0/X-ZC9wcmVhY3RAMTAuOC4y/deno/preact-render-to-string.js:4:1103)
at h (https://esm.sh/v87/preact-render-to-string@5.2.0/X-ZC9wcmVhY3RAMTAuOC4y/deno/preact-render-to-string.js:4:1103)
at m (https://esm.sh/v87/preact-render-to-string@5.2.0/X-ZC9wcmVhY3RAMTAuOC4y/deno/preact-render-to-string.js:3:684)
at render (https://deno.land/x/fresh@1.0.1/src/server/render.tsx:180:16)
at Object.render [as renderFn] (file:///.../main.ts:20:3)
at render (https://deno.land/x/fresh@1.0.1/src/server/render.tsx:184:14)如何解决此错误?我相信在script标记中包含所需的代码就足够了,但我很想知道是否有其他方法将代码合并到页面中,或者这是否是最好的方法。
发布于 2022-08-10 21:55:35
document是一个浏览器全局。它不存在于浏览器之外的环境中。
您需要添加一个检查,而不是假设document是通用定义的。
if (typeof document !== 'undefined') {
// use document
}实际上,您不应该在像Preact这样的UI框架中使用这样的浏览器全局。如果需要的话,您应该在包装元素中使用refs。
https://stackoverflow.com/questions/73305587
复制相似问题