现在的应用一般都支持主题切换的功能,包括暗黑模式和亮色模式,那么使用 React 框架怎么能快速的实现这一功能呢,本文就将通过 React Context 来实现它。
首先通过 vite 新建一个 React 项目
1.npm create vite@latest
2.输入项目名后使用 vscode 或者 webstorm 打开项目
3.因为 vite 没有下载依赖,所以需要打开项目后运行 npm install 安装所有的依赖
4.依赖安装完成后,可以运行 npm run dev,这里 vite 默认不会自动打开网页,可以通过在 package.json 里配置:
"scripts": {
"dev": "vite --open",
"build": "tsc && vite build",
"preview": "vite preview"
},
接下来就可以开始写代码了,在 src 目录下创建 ContextProvider.tsx 文件,首先在文件中创建两个类型用于约束 Context
// 主题模式
type TMode = "Light" | "Dark";
// StateContext 的类型
type TStateContext = {
// 当前的主题
currentMode: TMode;
// 设置主题
setMode: (mode: TMode) => void;
};
通过 React createContext API 创建 Context 对象,并将这个对象放到 useContext 这个 hook 中并导出,方便后续使用
const StateContext = createContext<TStateContext>({
currentMode: "Light",
setMode: () => {},
});
export const useStateContext = () => useContext(StateContext);
创建 ContextProvider 组件用来包裹子组件,使所有的子组件都能接收到 state context 的变化,并将 currentMode 和 修改主题的函数 setMode 传递下去
export const ContextProvider = ({ children }: any) => {
const [currentMode, setCurrentMode] = useState<TMode>("Light");
const setMode = (mode: TMode) => {
setCurrentMode(mode);
};
return (
<StateContext.Provider value={{ currentMode, setMode }}>
{children}
</StateContext.Provider>
);
};
接下来要找到根目录下的 main.tsx 将 App 组件用 ContextProvider 组件包裹
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<ContextProvider>
<App />
</ContextProvider>
</React.StrictMode>
)
接着就可以在 App.tsx 组件中使用刚刚创建的 Context 了,然后可以通过解构出来的 currentMode 和 setMode 来完成主题色的切换
import {Button} from "antd";
import {useStateContext} from "./ContextProvider";
function App() {
// 引入 useStateContext,解构出 currentMode, setMode 方法
const {currentMode, setMode} = useStateContext()
return (
<div style={currentMode == 'Light' ? {
backgroundColor: 'white',
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
height: '100vh'
} : {
backgroundColor: 'black',
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
height: '100vh'
}}>
<h1 style={currentMode == 'Light' ? {color: 'black'} : {color: 'white'}}>Hello App</h1>
<div style={{width: 500, height: 300, border: '1px solid #eee', borderRadius: '5px', padding: '10px'}}>
<div style={{display: 'flex', alignItems: 'center'}}>
<span style={currentMode == 'Light' ? {color: 'black'} : {color: 'white'}}>当前主题色</span>
<div style={currentMode == 'Light' ? {
backgroundColor: 'white',
width: 100,
height: 40,
borderRadius: '5px',
border: '1px solid #eee',
marginLeft: 10
} : {
backgroundColor: 'black',
width: 100,
height: 40,
borderRadius: '5px',
border: '1px solid #eee',
marginLeft: 10
}}/>
</div>
<div style={{marginTop: 10}}>
<Button onClick={() => setMode('Dark')}>更改成暗黑色</Button>
<Button onClick={() => setMode('Light')} style={{marginLeft: 10}}>更改成亮白色</Button>
</div>
</div>
</div>
)
}
export default App
最终的效果如下:
总结: 通过使用 React Context 还是很容易实现主题切换这种功能的,React Context 比较适合放的数据就是各层子组件都有可能会使用到的数据,比如这种颜色主题,相当于透传给各个子组件了。