React 应用的样式化组件高级用法 - 第一部分

2025-06-07

React 应用的样式化组件高级用法 - 第一部分

在我之前关于样式化组件的文章中,我写了样式化组件的一般特性、如何设置和使用它们以及为什么在 React 应用程序中使用它们。

这篇文章将介绍并展示 Styled Components 的一些高级用法,因此您将对其灵活性有更广泛的了解,并可能学习和使用一些技巧。

我们已经知道,styled-components是一个库,它可以帮助你创建已经带有样式的组件。它移除了组件和样式之间的映射。这意味着,当你定义样式时,你实际上是在创建一个普通的 React 组件,并将你的样式附加到它上面。

那么,让我们开始练习并学习新功能吧。我们将创建一个汉堡菜单,用于移动端的响应式应用。

我们的菜单将是一个单独的样式组件,它将由更小的样式组件创建而成。菜单将由MenuButtonMenuNavigation组件组成。
我们创建一个名为“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>
    </>
  );
}


Enter fullscreen mode Exit fullscreen mode

下一步是样式设置。我们创建一个名为“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;
`;


Enter fullscreen mode Exit fullscreen mode

之后,我们需要将所有创建的样式组件导入到 Menu.js 文件中,以便使用它们:



import {
  MenuButton,
  Line,
  MenuNavigation,
  NavList,
  NavItem,
  NavLink
} from "./Menu.styles";


Enter fullscreen mode Exit fullscreen mode

以上就是我们为应用程序中每个组件添加的一些通用样式。
目前,我们的导航链接看起来完全一样,但如果我们希望“关于”链接有所不同,该怎么办?

根据 Props 改变风格

由于我们的样式化 NavLink 是一个组件,因此它props在底层接受参数。我们可以将一个函数(“插值”)传递给样式化组件的模板字面量,以便根据接收到的 props 进行适配。

我们将属性传递给 NavLink 组件(我们称之为green),现在我们就可以通过 在 NavLink 中使用它了props

// 菜单.js



<NavLink green href="/">About</NavLink>


Enter fullscreen mode Exit fullscreen mode

// 菜单.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;
  `}`


Enter fullscreen mode Exit fullscreen mode

现在它的样式已经不同了。这真是太棒了!:) 但我们能做的还不止这些props

根据 Props 改变特定属性的样式

如果我们只想更改特定组件的某个属性的样式怎么办?我们也可以使用 来实现props

目前,我们的页面上同时显示了菜单按钮和导航链接,但这并不是我们真正想要的。我们希望仅在点击按钮时才显示导航链接。该如何实现呢?

我们可以display通过属性传递所需的行为(在我们的例子中是字符串)来更改 MenuNavigation 的属性display

// 菜单.js



<MenuNavigation display={"none"} />


Enter fullscreen mode Exit fullscreen mode

//菜单.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}
`;


Enter fullscreen mode Exit fullscreen mode

现在我们再也看不到导航链接了。但这也不是我们想要的效果。我们希望display动态地改变:点击菜单按钮时,我们希望看到导航链接;再次点击按钮时,我们希望它们再次折叠起来。让我们来实现它!

## 根据 Props 动态改变特定属性的样式

为了实现上述行为,我们需要将truefalse传递给display属性 (Attribute),并根据该值display将属性 (Property) 更改为blocknone
为此,首先我们需要创建一个state

//菜单.js



import { useState } from "react";
const [display, setDisplay] = useState(false);


Enter fullscreen mode Exit fullscreen mode

我们将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>
    </>
  );
}



Enter fullscreen mode Exit fullscreen mode

//菜单.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}
`;


Enter fullscreen mode Exit fullscreen mode

这里我们通过组件接收display属性,并且需要根据是否获取或以某种方式更改属性。该怎么做呢?propsdisplaytruefalse

带有样式组件的三元运算符

我们可以使用三元运算符有条件地更改属性的样式。在我们的示例中,我们将像这样
编写属性的逻辑: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"}
`;


Enter fullscreen mode Exit fullscreen mode

现在,按钮和导航都设置好了,正如我们想要的那样。但我们仍然需要进行一些调整。例如,设置一些媒体查询,这样我们才能在小屏幕上只看到汉堡菜单。或者,我们想为链接或按钮添加一些样式hoveractive伪类,对吗?或者,我们想className在组件中添加一个属性并使用它?这些我们都可以做到……不过,我会在下一篇博文中讲解!

所以请继续关注,也许你会像我一样喜欢 Styled Components :)

PS:如果需要,您可以在此处找到该项目的链接。

感谢您阅读我的博客。欢迎在LinkedInTwitter上与我联系:)

在 ko-fi.com 给我买杯咖啡

文章来源:https://dev.to/olenadrugalya/advanced-usage-of-styled-components-for-your-react-app-2hfh
PREV
React 应用的样式化组件简介
NEXT
掌握 Angular 8:了解这五件事可以节省您的时间。