react【实战】首页 -- 白天/黑夜主题切换(含组件封装)
最终效果组件封装技术栈: react19 Tailwind CSSsrc/components/darkToggle.jsximport{FiSun}fromreact-icons/fi;import{FaRegMoon,FaMoon}fromreact-icons/fa;import{useState,useEffect}fromreact;functionDarkToggle(){const[isDark,setIsDark]useState((){constsavedThemelocalStorage.getItem(theme);consthasDarkClassdocument.documentElement.classList.contains(dark);returnsavedThemedark||(!savedThemehasDarkClass);});useEffect((){if(isDark){document.documentElement.classList.add(dark);}else{document.documentElement.classList.remove(dark);}},[isDark]);consttoggleDark(){constnewDark!isDark;setIsDark(newDark);localStorage.setItem(theme,newDark?dark:light);};return(button classNamep-2 rounded-full cursor-pointer transition-all duration-300 grouponClick{toggleDark}aria-label切换深色模式{isDark?(FiSun size{20}classNametext-amber-400 transition-all duration-300 hover:rotate-90/):(div classNamerelativeFaRegMoon size{20}classNametext-gray-700 dark:text-gray-300 transition-all duration-150 group-hover:opacity-0/FaMoon size{20}classNametext-black dark:text-white absolute top-0 left-0 transition-all duration-150 opacity-0 group-hover:opacity-100 group-hover:scale-90//div)}/button);}exportdefaultDarkToggle;使用1. 配置 Tailwind CSS让其支持手动切换主题src/index.css在全局样式文件中添加下方代码importtailwindcss;/* 当根元素有 classdark 时 → 激活 dark: 样式用于在页面上切换主题为暗黑模式 */custom-variantdark(:where(.dark,.dark *));2. 导入渲染组件importDarkTogglefrom./DarkToggle;DarkToggle/3. 给页面添加黑夜的主题样式以导航 nav 为例添加了黑夜的主题样式dark:bg-black/90图标 logo 添加了黑夜的主题样式dark:fill-white特别注意因范例中 logo 使用的 svg 图标需用 fill- 的语法来填充颜色范例的完整代码如下importLogofrom../assets/apple.svg?react;import{AiOutlineMenu,AiOutlineSearch}fromreact-icons/ai;import{useState}fromreact;importDarkTogglefrom./DarkToggle;constHeader(){const[isOpen,setIsOpen]useState(false);const[isSearchEnable,setIsSearchEnable]useState(false);const[searchValue,setSearchValue]useState();return(nav classNameflex gap-2 items-center justify-between px-4 h-16 shadow-md sticky top-0 z-50 bg-white/70 backdrop-blur-md dark:bg-black/90 transition-all duration-100 a href#classNametext-xl font-boldLogo classNamew-6 h-6 hover:scale-105 transition-transform dark:fill-white//adiv classNamegap-6 hidden md:flex mx-auto dark:text-whitea href#商店/aa href#电脑/aa href#手机/aa href#智能家居/aa href#娱乐/aa href#技术支持/a/div{isSearchEnable(div classNamerelativeinput idsearch-inputclassNamepeer border border-gray-300 px-4 py-2 w-64 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition dark:border-gray-700 dark:bg-black/90 dark:text-whiteplaceholder value{searchValue}onChange{(e)setSearchValue(e.target.value)}/label htmlForsearch-inputclassNameabsolute left-2-top-2bg-white px-2text-xs text-gray-500transition-all duration-100cursor-pointer peer-placeholder-shown:top-2peer-placeholder-shown:text-sm peer-focus:-top-2peer-focus:left-2peer-focus:text-blue-500peer-focus:text-xs dark:text-white dark:bg-black/90搜索/label{searchValue(button onClick{()setSearchValue()}classNameabsolute right-4 top-2 text-gray-400 hover:text-gray-600 cursor-pointer peer-focus:text-blue-500✕/button)}/div)}div classNameflex gap-2 ml dark:text-white button onClick{()setIsSearchEnable(!isSearchEnable)}classNamecursor-pointerAiOutlineSearch size{24}//buttonDarkToggle/button classNamemd:hidden cursor-pointeronClick{()setIsOpen(true)}AiOutlineMenu size{24}//button/divdiv className{md:hidden fixed top-0 right-0 h-full w-64${!isOpenhidden}}div classNameflex flex-col mt-17 space-y-6 bg-white text-center p-6 rounded-lga href#商店/aa href#电脑/aa href#手机/aa href#智能家居/aa href#娱乐/aa href#技术支持/a/div/div{/* 移动端菜单展开时导航栏添加模糊遮罩 */}{isOpen(div classNamefixed inset-0 bg-black/50 backdrop-blur-mdonClick{()setIsOpen(false)}/div)}/nav);};exportdefaultHeader;