我正在使用 preline 并在动态页面中,为什么我必须一遍又一遍地重新初始化它。有人建议使用突变观察者,但这感觉不对,我使用的 nextjs 不应该是一个 spa 并且只需要初始化一次。
我在预行中使用下拉组件。这是典型的模式还是我做错了什么?
// utils/preline.ts
let prelineInitialized = false;
export const initPreline = () => {
if (typeof window === 'undefined' || prelineInitialized) return;
import('preline/preline').then(({ HSDropdown }) => {
const initDropdowns = () => {
document.querySelectorAll('.hs-dropdown').forEach(el => {
if (!el.classList.contains('hs-dropdown-initialized')) {
new HSDropdown(el);
el.classList.add('hs-dropdown-initialized');
}
});
};
// Initial initialization
initDropdowns();
// Set up MutationObserver to watch for new dropdowns
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node instanceof HTMLElement) {
if (node.classList.contains('hs-dropdown') && !node.classList.contains('hs-dropdown-initialized')) {
new HSDropdown(node);
node.classList.add('hs-dropdown-initialized');
} else {
node.querySelectorAll('.hs-dropdown:not(.hs-dropdown-initialized)').forEach(el => {
new HSDropdown(el);
el.classList.add('hs-dropdown-initialized');
});
}
}
});
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
prelineInitialized = true;
});
};
这可能不是解决方案,但可能会有所帮助。我也经历过类似的情况。让我解释一下我正在做什么来解决这个问题。
我正在使用 Preline HS 覆盖,我遇到了与您描述的完全相同的问题。
export default function Modal({
id,
title,
close = true,
width = "sm:max-w-lg",
content,
colophon,
}: Props) {
const session = useAuth((state) => state.session);
useEffect(() => {
const id = setTimeout(() => window.HSOverlay.autoInit(), 2000);
return () => clearTimeout(id);
}, [session]);
/**
* Get class names for modal inner content.
*
* @returns {string} - The class names.
* @since 1.0.0
*/
const entryClass = (): string => {
return mc(
`modalInner hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 mt-8 mb-8 opacity-0 ease-out transition-all sm:w-full m-3 sm:mx-auto h-full flex items-center overflow-hidden relative ${width}`
);
};
return (
<div
id={id}
className="modalWrapper hidden hs-overlay backdrop-blur-sm hs-overlay-backdrop-open:bg-white/[0.5] dark:hs-overlay-backdrop-open:bg-zinc-950/[0.9] size-full fixed top-0 start-0 z-[80] overflow-hidden"
>
<div className={entryClass()}>
<div className="flex flex-col w-full bg-white border border-gray-200 rounded-2xl shadow-lg overflow-hidden dark:bg-zinc-950 dark:border-zinc-800">
<Header id={id} title={title} close={close} />
<Content>{content}</Content>
{colophon && <Colophon>{colophon}</Colophon>}
</div>
</div>
</div>
);
}
我注意到当组件动态/有条件渲染时,我需要调用
autoinit()
静态方法。看看useEffect
。
useEffect(() => {
const id = setTimeout(() => window.HSOverlay.autoInit(), 2000);
return () => clearTimeout(id);
}, [session]);
HS 选项卡的另一个示例。
const Navigation = () => {
const session = useAuth((state) => state.session);
useEffect(() => {
const id = setTimeout(() => window.HSTabs.autoInit(), 2000);
return () => clearTimeout(id);
}, [session]);
/**
* Get tab nav item css class names.
*
* @returns {string} The tab nav item css class names.
* @since 1.0.0
*/
const navClass = (): string => {
return "hs-tab-active:border-blue-500 hs-tab-active:text-blue-600 p-0 pe-10 inline-flex items-center gap-x-2 border-e border-transparent text-md whitespace-nowrap text-gray-600 hover:text-blue-600 focus:outline-none focus:text-blue-600 disabled:opacity-50 disabled:pointer-events-none dark:text-gray-200 dark:hover:text-blue-400 hs-tab-active:dark:border-blue-400 dark:focus:text-blue-400 transition-colors ease-in duration-300";
};
/**
* Define tab nav items.
*
* @since 1.0.0
*/
const nav = [
{
label: "Account",
class: navClass() + " active",
id: "#tabContentAccount",
icon: "account",
},
{
label: "Preferences",
class: navClass(),
id: "#tabContentPreferences",
icon: "settings",
},
];
return (
<div className="flex flex-col flex-shrink-0 relative border-e border-gray-100 dark:border-zinc-800">
<nav
className="flex flex-col gap-6"
aria-label="Tabs"
role="tablist"
data-hs-tabs-vertical="true"
>
{nav.map((item, index) => (
<button
key={index}
type="button"
className={item.class}
data-hs-tab={item.id}
aria-controls={item.id.replace("#", "")}
role="tab"
>
{item?.icon === "account" ? (
<IconSticker clasX="size-6" />
) : (
<IconSettings name="type-2" clasX="size-6" />
)}
{item.label}
</button>
))}
</nav>
</div>
);
};
再次注意到我正在使用
window.HSTabs.autoInit();
方法。
希望这有帮助。