You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中如何一次性定义darkmode-js包并在多页面复用?

问题

我是Next.js新手,对代码结构有疑问。我有两个页面:PostList (index.js)和PostSingle ([postId].js),想要在两个页面中添加深色/浅色主题切换按钮,因此使用了darkmode-js包。该包的初始化代码如下:

const options = {
  bottom: "64px",
  right: "32px",
  left: "unset",
  time: "0.5s",
  mixColor: "#fff",
  backgroundColor: "#fff",
  buttonColorDark: "#100f2c",
  buttonColorLight: "#fff",
  saveInCookies: false,
  label: "🌓",
  autoMatchOsTheme: true,
};

const darkmode = new Darkmode(options);
darkmode.showWidget();

目前我在两个页面分别导入import Darkmode from "darkmode-js";,定义options并调用darkmode.showWidget();,示例如下:

import Darkmode from "darkmode-js";

const PostsList = (props) => {
    // All that package stuff here
    return ( ...

和

import Darkmode from "darkmode-js";

const PostsSingle = (props) => {
    // All that package stuff here
    return ( ...

但我认为这种结构不合理,请问有没有更好的方法可以一次性定义该包并在需要的地方复用?


解决方案

方法1:自定义Hook

将darkmode的初始化逻辑封装为自定义Hook,在需要的页面直接调用:

// hooks/useDarkmode.js
import Darkmode from "darkmode-js";

export default function useDarkmode() {
  const options = {
    bottom: "64px",
    right: "32px",
    left: "unset",
    time: "0.5s",
    mixColor: "#fff",
    backgroundColor: "#fff",
    buttonColorDark: "#100f2c",
    buttonColorLight: "#fff",
    saveInCookies: false,
    label: "🌓",
    autoMatchOsTheme: true,
  };

  const initDarkmode = () => {
    const darkmode = new Darkmode(options);
    darkmode.showWidget();
  };

  return { initDarkmode };
}

页面中使用示例:

// pages/index.js (PostList)
import useDarkmode from "../hooks/useDarkmode";
import { useEffect } from "react";

const PostsList = (props) => {
  const { initDarkmode } = useDarkmode();
  
  // 组件挂载时初始化主题切换
  useEffect(() => {
    initDarkmode();
  }, []);

  return (
    // 页面内容
  );
};

PostSingle页面只需同样导入该Hook并调用initDarkmode即可。

方法2:全局Layout组件(推荐)

如果你的页面有统一的布局容器,把darkmode初始化逻辑放在Layout组件中,所有使用该Layout的页面都会自动加载主题切换按钮:

// components/Layout.js
import Darkmode from "darkmode-js";
import { useEffect } from "react";

const Layout = ({ children }) => {
  useEffect(() => {
    const options = {
      bottom: "64px",
      right: "32px",
      left: "unset",
      time: "0.5s",
      mixColor: "#fff",
      backgroundColor: "#fff",
      buttonColorDark: "#100f2c",
      buttonColorLight: "#fff",
      saveInCookies: false,
      label: "🌓",
      autoMatchOsTheme: true,
    };

    const darkmode = new Darkmode(options);
    darkmode.showWidget();
  }, []);

  return (
    <div className="layout-container">
      {/* 这里可以放导航栏、页脚等公共元素 */}
      {children}
    </div>
  );
};

export default Layout;

页面中用Layout包裹内容:

// pages/index.js
import Layout from "../components/Layout";

const PostsList = (props) => {
  return (
    <Layout>
      {/* PostList的页面内容 */}
    </Layout>
  );
};

这种方式无需每个页面单独处理,适合全局复用场景。

方法3:工具函数封装

将初始化逻辑抽成独立的工具函数,在需要的页面引入调用:

// utils/darkmode.js
import Darkmode from "darkmode-js";

export const initDarkmode = () => {
  const options = {
    bottom: "64px",
    right: "32px",
    left: "unset",
    time: "0.5s",
    mixColor: "#fff",
    backgroundColor: "#fff",
    buttonColorDark: "#100f2c",
    buttonColorLight: "#fff",
    saveInCookies: false,
    label: "🌓",
    autoMatchOsTheme: true,
  };

  const darkmode = new Darkmode(options);
  darkmode.showWidget();
};

页面中使用示例:

// pages/[postId].js
import { initDarkmode } from "../utils/darkmode";
import { useEffect } from "react";

const PostsSingle = (props) => {
  useEffect(() => {
    initDarkmode();
  }, []);

  return (
    // 页面内容
  );
};

内容的提问来源于stack exchange,提问作者Martin AJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:41:30