📜  如何为你的 React App 添加双主题?

📅  最后修改于: 2022-05-13 01:56:51.526000             🧑  作者: Mango

如何为你的 React App 添加双主题?

双主题如今在网站中非常普遍,最常见的是浅色和深色版本,越来越多的应用程序和网站都包含此功能。对于 React 应用程序,Material UI 框架使用多个主题提供了非常有用的功能,并且它们之间的切换非常容易。

我们将创建一个简单的 React 应用程序,并使用 Switch 组件在 Dark 和 Light 主题之间切换。

创建 React 应用程序并安装模块:

  • 第 1 步:使用以下命令创建一个 React 应用程序:

    npx create-react-app gfg
  • 第 2 步:创建项目文件夹后,即 gfg 使用以下命令移动到该文件夹:

    cd gfg
  • 第 3 步:创建 ReactJS 应用程序后,使用以下命令安装material-ui模块:

    npm install @material-ui/core
  • 步骤 4:src文件夹中创建以下两个新文件:

    • theme.js:在这个文件中,我们将定义我们的主题对象。
    • Component1.js:这是我们的示例子组件。

项目结构:它将如下所示。

useTheme 钩子:

我们可以从主题文件中导入多个主题,然后使用 Switch 组件及其处理函数在父组件中切换主题。但是问题来了,它的子组件和进一步嵌套的组件呢?

在单一主题架构中,应用程序的所有组件都可以直接从 theme.js 文件中导入主题对象并使用它。现在,既然有双重主题,他们怎么知道主题的变化?我们是否必须传递一个 prop 来分别通知每个组件“嘿,活动主题已更改”,这将是一种非常麻烦且低效的方法。

幸运的是,Material-UI 提供了一个钩子useTheme ,通过它我们可以访问 React 组件中的父主题变量。所以我们不需要单独导入主题,可以使用父组件使用的任何主题对象。因此,现在即使我们更改主题,它也会在整个组件树中发生更改。

句法:

import { useTheme } from '@material-ui/core/styles';

function Component1() {
  const theme = useTheme();
}

创建深色主题对象:

尽管 Material UI 带有内置的明暗模式,但我们将单独定义暗主题对象,因为我们可以自由地更改两个主题中的每个属性,或者您甚至可以想要一个灰色主题而不是黑暗的主题。

const darkTheme = responsiveFontSizes(createMuiTheme({
  spacing: 4,
}));

我们将保持 darkTheme 的字体和排版与原始字体相同。我们将背景更改为黑色,将调色板的主要/次要颜色更改为白色,如下所示。

theme.js
import { createMuiTheme, responsiveFontSizes } from '@material-ui/core/styles';
  
const lightTheme = responsiveFontSizes(createMuiTheme({
  spacing: 4,
  typography: {
    fontFamily: [
      'Roboto',
      'Raleway',
      'Open Sans',
    ].join(','),
    h1: {
      fontSize: '5rem',
      fontFamily: 'Raleway',
    },
    h3: {
      fontSize: '2.5rem',
      fontFamily: 'Open Sans',
    },
  },
  palette: {
    background: {
      default: '#009900'//green
    },
    primary: {
      main: '#009900',//green
    },
    secondary:{
      main: '#000000',//black
      icons: '#009900', //white
    },
    text: {
      primary: '#000000',//black
      secondary: '#FFFFFF',//white
    },
  },
}));
  
const darkTheme = responsiveFontSizes(createMuiTheme({
  spacing: 4,
  typography: {
    fontFamily: [
      'Roboto',
      'Raleway',
      'Open Sans',
    ].join(','),
    h1: {
      fontSize: '5rem',
      fontFamily: 'Raleway',
    },
    h3: {
      fontSize: '2.5rem',
      fontFamily: 'Open Sans',
    },
  },
  palette: {
    background: {
      default: '#000000'//black
    },
    primary: {
      main: '#FFFFFF',//white
    },
    secondary:{
      main: '#FFFFFF', //white
      icons: '#FFFFFF', //white
    },
    text: {
      primary: '#FFFFFF',//white
      secondary: '#FFFFFF',//white
    },
  },
}));
  
export default lightTheme ;
export {darkTheme} ;


Component1.js
import React, { Component } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { useTheme } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
  
const useStyles = makeStyles((theme) => ({
    root: {
        flexGrow: 1,
    },
}));
  
export default function Component1() {
    const theme = useTheme();
    const classes = useStyles(theme);
    return (
        
                         This is a Child Component text.                    
    ); }


App.js
import React, { Component } from 'react';
import './App.css';
import CssBaseline from '@material-ui/core/CssBaseline';
import { ThemeProvider } from '@material-ui/styles';
import { createMuiTheme } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import { AppBar, Toolbar } from '@material-ui/core';
import Switch from '@material-ui/core/Switch';
import lightTheme, { darkTheme } from './theme';
import Grid from '@material-ui/core/Grid';
import Component1 from './Component1';
  
function App() {
  // The 'checked' state is for the status of Switch component
  const [checked, setChecked] = React.useState(false);
  // The 'newtheme' state tells if the new theme (i.e, dark theme) 
  // is to be applied or not.
  const [newtheme, setTheme] = React.useState(false);
  function changeTheme() {
    setTheme(!newtheme);
    setChecked(!checked);
  }
  // Conditional - if newtheme is set to true
  // then set appliedTheme to dark
  const appliedTheme = 
     createMuiTheme(newtheme ? darkTheme : lightTheme);
  return (
    
      
        
        
          
            {/* Switch position whenever 
                changed triggers the changeTheme() */}
             { changeTheme() }} 
            style={{ color: appliedTheme.palette.secondary.icons }} />
          
        
        
          
            Geeks for Geeks
          
          
                     
                                                                                                                  
        
      
    
  ); }    export default App;


组件1.js

import React, { Component } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { useTheme } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
  
const useStyles = makeStyles((theme) => ({
    root: {
        flexGrow: 1,
    },
}));
  
export default function Component1() {
    const theme = useTheme();
    const classes = useStyles(theme);
    return (
        
                         This is a Child Component text.                    
    ); }

应用程序.js

import React, { Component } from 'react';
import './App.css';
import CssBaseline from '@material-ui/core/CssBaseline';
import { ThemeProvider } from '@material-ui/styles';
import { createMuiTheme } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import { AppBar, Toolbar } from '@material-ui/core';
import Switch from '@material-ui/core/Switch';
import lightTheme, { darkTheme } from './theme';
import Grid from '@material-ui/core/Grid';
import Component1 from './Component1';
  
function App() {
  // The 'checked' state is for the status of Switch component
  const [checked, setChecked] = React.useState(false);
  // The 'newtheme' state tells if the new theme (i.e, dark theme) 
  // is to be applied or not.
  const [newtheme, setTheme] = React.useState(false);
  function changeTheme() {
    setTheme(!newtheme);
    setChecked(!checked);
  }
  // Conditional - if newtheme is set to true
  // then set appliedTheme to dark
  const appliedTheme = 
     createMuiTheme(newtheme ? darkTheme : lightTheme);
  return (
    
      
        
        
          
            {/* Switch position whenever 
                changed triggers the changeTheme() */}
             { changeTheme() }} 
            style={{ color: appliedTheme.palette.secondary.icons }} />
          
        
        
          
            Geeks for Geeks
          
          
                     
                                                                                                                  
        
      
    
  ); }    export default App;

运行应用程序的步骤:从项目的根目录使用以下命令运行应用程序:

npm start

输出:现在打开浏览器并转到http://localhost:3000/ ,您将看到以下输出: