React 应用的样式化组件高级用法 - 第一部分
在我之前关于样式化组件的文章中,我写了样式化组件的一般特性、如何设置和使用它们以及为什么在 React 应用程序中使用它们。
这篇文章将介绍并展示 Styled Components 的一些高级用法,因此您将对其灵活性有更广泛的了解,并可能学习和使用一些技巧。
我们已经知道,styled-components是一个库,它可以帮助你创建已经带有样式的组件。它移除了组件和样式之间的映射。这意味着,当你定义样式时,你实际上是在创建一个普通的 React 组件,并将你的样式附加到它上面。
那么,让我们开始练习并学习新功能吧。我们将创建一个汉堡菜单,用于移动端的响应式应用。
我们的菜单将是一个单独的样式组件,它将由更小的样式组件创建而成。菜单将由MenuButton和MenuNavigation组件组成。
我们创建一个名为“Menu.js”的文件,并在其中添加以下代码:
export const Menu = () => {
return (
<>
<MenuButton>
<Line></Line>
<Line></Line>
<Line></Line>
</MenuButton>
<MenuNavigation>
<NavList>
<NavItem>
<NavLink href="/">Home</NavLink>
</NavItem>
<NavItem>
<NavLink href="/">About</NavLink>
</NavItem>
</NavList>
</MenuNavigation>
</>
);
}
下一步是样式设置。我们创建一个名为“Menu.styles.js”的文件,并在其中添加以下代码:
import styled from "styled-components";
export const MenuButton = styled.div`
cursor: pointer;
width: 3rem;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
`;
export const Line = styled.div`
width: 80%;
height: 3px;
background-color: white;
margin: 0.2rem;
`;
export const MenuNavigation = styled.div`
position: fixed;
width: 200px;
max-width: 70%;
height: 100%;
left: 0;
margin-top: 1.4rem;
z-index: 200;
background-color: white;
padding: 1rem 2rem;
transition: all 0.7s ease;
box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
`;
export const NavList = styled.ul`
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: column;
align-items: center;
`;
export const NavItem = styled.li`
margin: 5px 0;
box-sizing: border-box;
width: 100%;
display: block;
`;
export const NavLink = styled.a`
color: #8f5c2c;
text-decoration: none;
width: 100%;
box-sizing: border-box;
display: block;
padding: 0.5rem;
`;
之后,我们需要将所有创建的样式组件导入到 Menu.js 文件中,以便使用它们:
import {
MenuButton,
Line,
MenuNavigation,
NavList,
NavItem,
NavLink
} from "./Menu.styles";
以上就是我们为应用程序中每个组件添加的一些通用样式。
目前,我们的导航链接看起来完全一样,但如果我们希望“关于”链接有所不同,该怎么办?
根据 Props 改变风格
由于我们的样式化 NavLink 是一个组件,因此它props
在底层接受参数。我们可以将一个函数(“插值”)传递给样式化组件的模板字面量,以便根据接收到的 props 进行适配。
我们将属性传递给 NavLink 组件(我们称之为green
),现在我们就可以通过 在 NavLink 中使用它了props
:
// 菜单.js
<NavLink green href="/">About</NavLink>
// 菜单.styles.js
export const NavLink = styled.a`
color: #8f5c2c;
text-decoration: none;
width: 100%;
box-sizing: border-box;
display: block;
padding: 0.5rem;
${props => props.green &&`
background: green;
color: white;
`}`
现在它的样式已经不同了。这真是太棒了!:) 但我们能做的还不止这些props
。
根据 Props 改变特定属性的样式
如果我们只想更改特定组件的某个属性的样式怎么办?我们也可以使用 来实现props
。
目前,我们的页面上同时显示了菜单按钮和导航链接,但这并不是我们真正想要的。我们希望仅在点击按钮时才显示导航链接。该如何实现呢?
我们可以display
通过属性传递所需的行为(在我们的例子中是字符串)来更改 MenuNavigation 的属性display
:
// 菜单.js
<MenuNavigation display={"none"} />
//菜单.styles.js
export const MenuNavigation = styled.div`
position: fixed;
width: 200px;
max-width: 70%;
height: 100%;
left: 0;
margin-top: 1.4rem;
z-index: 200;
background-color: white;
padding: 1rem 2rem;
transition: all 0.7s ease;
box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
display:${props => props.display}
`;
现在我们再也看不到导航链接了。但这也不是我们想要的效果。我们希望display
动态地改变:点击菜单按钮时,我们希望看到导航链接;再次点击按钮时,我们希望它们再次折叠起来。让我们来实现它!
## 根据 Props 动态改变特定属性的样式
为了实现上述行为,我们需要将true或false传递给display
属性 (Attribute),并根据该值display
将属性 (Property) 更改为block
或none
。
为此,首先我们需要创建一个state
:
//菜单.js
import { useState } from "react";
const [display, setDisplay] = useState(false);
我们将display
变量初始化为false,因此如果现在使用它来设置display,我们将看不到除了按钮之外的任何内容。当我们点击 MenuButton 时,我们将display
变量更改为 true ,这样我们就应该能看到导航链接了。
我们来看看代码:
//菜单.js
import { useState } from "react";
import {MenuButton, Line, MenuNavigation, NavList, NavItem, NavLink} from "./Menu.styles";
export const Menu = () => {
const [display, setDisplay] = useState(false);
// This method will change display to opposite every time we call it
const handleClick = () =>{
setDisplay(!display);
}
return (
<>
<MenuButton onClick={handleClick}>
<Line></Line>
<Line></Line>
<Line></Line>
</MenuButton>
<MenuNavigation display={display}>
<NavList>
<NavItem>
<NavLink href="/">Home</NavLink>
</NavItem>
<NavItem>
<NavLink green href="/">About</NavLink>
</NavItem>
</NavList>
</MenuNavigation>
</>
);
}
//菜单.styles.js
export const MenuNavigation = styled.div`
position: fixed;
width: 200px;
max-width: 70%;
height: 100%;
left: 0;
margin-top: 1.4rem;
z-index: 200;
background-color: white;
padding: 1rem 2rem;
transition: all 0.7s ease;
box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
display:${props => props.display}
`;
这里我们通过组件接收display
属性,并且需要根据是否获取或以某种方式更改属性。该怎么做呢?props
display
true
false
带有样式组件的三元运算符
我们可以使用三元运算符有条件地更改属性的样式。在我们的示例中,我们将像这样
编写属性的逻辑:display
//菜单.styles.js
export const MenuNavigation = styled.div`
position: fixed;
width: 200px;
max-width: 70%;
height: 100%;
left: 0;
margin-top: 1.4rem;
z-index: 200;
background-color: white;
padding: 1rem 2rem;
transition: all 0.7s ease;
box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
display:${props => props.display ? "block" : "none"}
`;
现在,按钮和导航都设置好了,正如我们想要的那样。但我们仍然需要进行一些调整。例如,设置一些媒体查询,这样我们才能在小屏幕上只看到汉堡菜单。或者,我们想为链接或按钮添加一些样式hover
和active
伪类,对吗?或者,我们想className
在组件中添加一个属性并使用它?这些我们都可以做到……不过,我会在下一篇博文中讲解!
所以请继续关注,也许你会像我一样喜欢 Styled Components :)
PS:如果需要,您可以在此处找到该项目的链接。
感谢您阅读我的博客。欢迎在LinkedIn或Twitter上与我联系:)
文章来源:https://dev.to/olenadrugalya/advanced-usage-of-styled-components-for-your-react-app-2hfh