如何为你的 React Web 应用添加暗黑模式
先决条件
设置
有趣的部分
概括
附加功能
我们正处于一个万物皆暗黑模式的时代。如今,大多数应用程序都在导航栏或设置界面附近提供了一个开关,只需点击一下,屏幕就会变暗。有些应用程序甚至默认设置了暗黑模式,例如Mixer,甚至 Netflix 也默认设置了暗黑模式。
使用暗模式确实有助于减少由亮模式引起的眼睛疲劳,在本文结束时,您应该能够在几分钟内将暗模式添加到您的 Reactjs 应用程序中。
先决条件
您应该对以下内容有基本的了解:
- React 概念(生命周期)
- CSS 概念,尤其是 CSS 变量
- Javascript 文档对象模型
设置
创建一个新目录来存放我们的 React 应用程序。
$ mkdir simple_dark_theme_react_app && cd simple_dark_theme_react_app
接下来,我们需要create-react-app
CLI,它可以帮助我们在零 webpack 配置的情况下更快地设置一个简单的 React 应用程序。
$ npx create-react-app .
运行我们的应用程序
$ yarn start or npm start
它应该自动启动您的浏览器,如果没有,请访问http://localhost:3000
。
如果你碰巧遇到了一个
fsevents is not a constructor
关于它的问题,请访问这个 Github链接如果这没有帮助,我所做的就是删除
lock
文件和node_module
文件夹并重新安装软件包。
{
"name": "simple_dark_theme_react_app",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-scripts": "3.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
上面是我的 package.json 文件。
有趣的部分
我不会创建一个完整的 React 应用程序,因为这会使这篇博客很长,而且我希望您能够自由发挥创造力,而不会感到困惑。我将使用默认create-react-app
模板。
我们将做什么
我们将使用上述默认 React 应用背景颜色作为深色主题,白色作为浅色主题。页面下方会有一个开关,用于切换主题。
注意:我不会使用
react
钩子,因为我没有时间去研究它,而且类组件对我来说确实有用。
CSS 部分
在切换主题时,CSS 起着至关重要的作用。启动您常用的编辑器,打开src/App.css
我们需要添加一些变量的文件。
/* Define our color variables */
html {
--primary-color: #fff;
--secondary-color: #282c34;
}
/* Redefine our color variables if the data-theme attr
value is "dark
*/
html[data-theme="dark"] {
--primary-color: #282c34;
--secondary-color: #fff;
}
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
pointer-events: none;
}
.App-header {
background-color: var(--secondary-color);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: var(--primary-color);
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
接下来,我们将添加主题切换开关。打开src/App.js
文件。
import React from "react";
import logo from "./logo.svg";
import "./App.css";
class App extends React.Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<label class="switch">
<input type="checkbox" />
<span class="slider round" />
</label>
</header>
</div>
);
}
}
export default App;
请注意,我在文件中使用了一个类组件
src/App.js
。
我们需要添加一些 CSS 来设置切换按钮和打开src/App.css
文件的样式。
/* CSS styling for our switch */
/* This switch was styled with the help of w3schools */
/* https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_switch */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
Javascript/React 部分
注意:为了防止在刷新应用程序时丢失状态,我们将主题状态存储在浏览器的中
localStorage
。
打开你的src/App.js
文件,让我们更新它,以便我们可以在主题之间切换
import React from "react";
import logo from "./logo.svg";
import "./App.css";
class App extends React.Component {
// Define a state object to hold our app's state
state = {
// Boolean attribute that will allow us to toggle the switch
// Keep the switch on if the theme is dark
checked: localStorage.getItem("theme") === "dark" ? true : false,
/**
* When a user activates the dark theme we will store the value
* on localstorage or set default value to light if it is neither dark
* nor light
*/
theme: localStorage.getItem("theme")
};
componentDidMount() {
// Update the data-theme attribute of our html tag
document
.getElementsByTagName("HTML")[0]
.setAttribute("data-theme", localStorage.getItem("theme"));
}
// Class method allowing us to toggle the theme change
toggleThemeChange = () => {
const { checked } = this.state;
// If theme is light then change to dark
if (checked === false) {
// Update localstorage
localStorage.setItem("theme", "dark");
/**
* The document.getElementsByTagName(...).setAttribute(...)
* will only update the value
*/
// Update the data-theme attribute of our html tag
document
.getElementsByTagName("HTML")[0]
.setAttribute("data-theme", localStorage.getItem("theme"));
// Update our state
this.setState({
// Ensure our switch is on if we change to dark theme
checked: true
});
} else {
// Update localstorage
localStorage.setItem("theme", "light");
/**
* The document.getElementsByTagName(...).setAttribute(...)
* will only update the value until the App is mounted and we change
* the state of the switch so we will need to introduce
* a React lifecycle called ˝componentDidMount()˝
*/
// Update the data-theme attribute of our html tag
document
.getElementsByTagName("HTML")[0]
.setAttribute("data-theme", localStorage.getItem("theme"));
// Update our state
this.setState({
// Ensure our switch is off if we change to light theme
checked: false
});
}
};
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>Click the switch to toggle themes</p>
<label class="switch">
{/* checked attribute is used to determine the state of
checkbox
----------------------------------------------
The onChange attribute will toggle our theme change
*/}
<input
type="checkbox"
// checked={this.state.checked}
defaultChecked={this.state.checked}
onChange={() => this.toggleThemeChange()}
/>
<span class="slider round" />
</label>
</header>
</div>
);
}
}
export default App;
概括
在这篇博客中,我们能够为我们的反应应用程序添加暗模式。
附加功能
Hooks 版本
https://gist.github.com/Oxyrus/b4edab0372b3c9b1c1b60a59e7955121
文章来源:https://dev.to/wchr/how-to-add-a-dark-mode-to-your-react-web-app-4f1