json - 如何在 react 和 styled-components 中使用 json 文件切换主题?
问题描述
我已经为此工作了好几天,但我仍然被困住了,所以我真的可以使用一些帮助。
我已经尝试了一些我在网上找到的东西,并且一些东西有效。但它们要么非常复杂和繁琐,要么在某种程度上不是这样,因此我可以重新排列它们以在我的项目中按照我的意愿工作。
我有一些要求,我希望遵循:
- JSON 文件中的主题
- 加载页面时将主题加载到 localStorage,
- 使用钩子和样式组件。
目前,JSON 文件加载到 localStorage,按钮获取它们的字体和颜色,程序注册按下哪个按钮。
目标是按下一个主题按钮,主题背景和主页都会相应地更改颜色和字体。
这是重要的部分!
import { useState, useEffect } from 'react';
import styled from 'styled-components';
import data from './ThemeData.json';
import _ from 'lodash';
import WebFont from 'webfontloader';
import { ThemeProvider } from "styled-components";
const ThemeContainer = styled.div`
position: absolute;
height: 15rem;
width: 100%;
max-width: 80rem;
top: 0;
left: 50%;
transform: translateX(-50%);
background: #ededed;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
box-shadow: 0 .2rem .4rem rgba(0,0,0,.3);
`
const ThemeCard = styled.li`
height: 6rem;
width: 12rem;
border: .1rem solid #222;
display: flex;
justify-content: center;
align-items: center;
margin: 0 1rem;
border-radius: .5rem;
background: red;
`
const ThemeButton = styled.button`
height: 4rem;
width: 10rem;
margin: 0 1rem;
display: flex;
justify-content: center;
align-items: center;
border: .1rem solid #333;
border-radius: .4rem;
outline: none;
box-shadow: 0 .2rem .4rem rgba(0,0,0, .6);
transition: .2s ease-out;
&:hover{
box-shadow: none;
}
`
const ThemeSection = () => {
const [theme, setTheme] = useState(data, () => {
const localData = localStorage.getItem('themes');
return JSON.parse(localData)
});
useEffect(() => {
localStorage.setItem('themes', JSON.stringify(theme));
setTheme(theme)
}, [theme]);
function ThemeSwitcher(selectedTheme) {
console.log(selectedTheme);
setTheme(theme)
}
const getFonts = () => {
const allFonts = _.values(_.mapValues(data, 'font'));
return allFonts;
}
useEffect(() => {
WebFont.load({
google: {
families: getFonts()
}
});
});
return (
<>
<ThemeContainer>
{theme.map(theme => (
<ThemeCard theme={theme[theme]} key={theme.id}
style={{
background: `${theme.themeCard}`
}}>
<ThemeButton onClick={() => { ThemeSwitcher(theme) }}
style={{
background: `${theme.background}`,
color: `${theme.text}`,
fontFamily: `${theme.font}`
}}
>{theme.title}</ThemeButton>
</ThemeCard>
))
}
</ThemeContainer>
</>
)
}
export default ThemeSection
全球风格:
import { createGlobalStyle } from 'styled-components';
export const GlobalStyle = createGlobalStyle`
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: inherit;
}
html {
font-size: 62.5%;
}
body {
box-sizing: border-box;
font-family: 'montserrat', sans-serif;
}
a {
text-decoration: none;
}
ul, li {
list-style: none;
}
`;
应用程序.js
import { GlobalStyle } from './globalStyle'
import MainPage from './components/MainPage'
function App() {
return (
<>
<GlobalStyle />
<MainPage />
</>
);
}
export default App;
主页:
import { MainSection, MainBox, MainText } from './MainPage.elements'
import ThemeSection from './theme/ThemeSection'
const MainPage = () => {
return (
<>
<MainSection>
<ThemeSection />
<MainBox>
<MainText>just some random text</MainText>
</MainBox>
</MainSection>
</>
)
}
export default MainPage
造型:
import styled from 'styled-components';
export const MainSection = styled.section`
height: 100vh;
width: 100%;
max-width: 80rem;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
background: #f4c9b7;
`;
export const MainBox = styled.ul`
height: 50%;
width: 100%;
background: #f4dfd6;
display: flex;
justify-content: center;
align-items: center;
`;
export const MainText = styled.h5`
text-align: center;
color: #333;
font-size: clamp(3rem, 4vw, 5rem);
text-transform: capitalize;
padding: 0 3rem;
`;
JSON 文件:
[
{
"id": "001",
"title": "light",
"sectionBackground": "#ffffff",
"themeCard": "#ffffff",
"background": "#ededed",
"text": "#333",
"font": "Tino"
},
{
"id": "002",
"title": "dark",
"sectionBackground": "#333333",
"themeCard": "#666666",
"background": "#111111",
"text": "#f1f1f1",
"font": "Lato"
},
{
"id": "003",
"title": "purple",
"sectionBackground": "#d0b7f4",
"themeCard": "#d0b7f4",
"background": "#7852ae",
"text": "#999",
"font": "Oswald"
}
]
我试图用 stackblitz 来解决这个问题,但恐怕也没有运气。
非常感谢!
解决方案
推荐阅读
- homebrew - Homebrew 查找不依赖于任何其他已安装软件包的已安装软件包
- bash - 在 G1GC 中计算 TotalHeap 大小
- html - 另一个 div 上的可滚动层
- php - 我想获得 Laravel 和 MySQL 的总库存
- jquery - 当父母检查孩子时创建?
- ios - 使用 UITableView 的老虎机动画
- bash - 用 bash 中的选项卡文件值填充参数
- php - 使用 fopen() fputcsv() fclose() VS。print() 并将显示重定向到文件中
- javascript - socket.on() 和 socket.once() 之间的区别
- java - 重构 JDK 8 代码以删除冗余方法调用