3

使用样式化组件,我想构建一个 React 组件,它将模仿W3 Schools中的以下代码:

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
}

li {
  float: left;
}

li a, .dropbtn {
  display: inline-block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

li a:hover, .dropdown:hover .dropbtn {
  background-color: red;
}

li.dropdown {
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
}

.dropdown-content a:hover {background-color: #f1f1f1;}

.dropdown:hover .dropdown-content {
  display: block;
}
<body>

<ul>
  <li><a href="#home">Home</a></li>
  <li><a href="#news">News</a></li>
  <li class="dropdown">
    <a href="javascript:void(0)" class="dropbtn">Dropdown</a>
    <div class="dropdown-content">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>
  </li>
</ul>

<h3>Dropdown Menu inside a Navigation Bar</h3>
<p>Hover over the "Dropdown" link to see the dropdown menu.</p>

</body>
</html>

这是我的反应组件:

import React, { Component } from "react";
import PropTypes from "prop-types";
import styled, { ThemeProvider } from "styled-components";


const StyledUl = styled.ul`
    list-style-type: none;
    margin: 0;
    overflow: hidden;
    background-color: #333;
    padding: 0px;
    background-color: lightblue;
    color: black;
    font-weight: bold;
`;

const StyledLi = styled.li`
    float: left;
    height: 100%;
    padding: 10px;
    &:hover {
        background-color: red;
    }
`;

const DropDownContent = styled.div`
    display: none;
    position: absolute;
    min-width: 160px;
    z-index: 1;
`;

const DropDownLi = styled(StyledLi)`
    display: inline-block;
    &:hover ${DropDownContent} {
        display: block;
    }
`;

const StyledA = styled.a`
    display: inline-block;
    text-align: center;
    text-decoration: none;
`;

const SubA = styled(StyledA)`
    text-decoration: none;
    display: block;
    text-align: left;
    background-color: lightblue;
    padding: 10px;
`;

class Menu extends Component {
    handleClick = action => {
        if (!action) return;

        if (this.props.onClick) this.props.onClick(action);
    };

    render = () => {
        return (
            <StyledUl>
                <StyledLi>
                    <StyledA onClick={() => this.handleClick("Home")}>
                        Home
                    </StyledA>
                </StyledLi>
                <StyledLi>
                    <StyledA onClick={() => this.handleClick("News")}>
                        Home
                    </StyledA>
                </StyledLi>
                <DropDownLi>
                    <StyledA onClick={() => this.handleClick("DropDown")}>
                        DropDown
                    </StyledA>
                    <DropDownContent>
                        {" "}
                        <SubA onClick={() => this.handleClick("Link1")}>
                            Link 1
                        </SubA>
                        <SubA onClick={() => this.handleClick("Link2")}>
                            Link 2
                        </SubA>
                        <SubA onClick={() => this.handleClick("Link3")}>
                            Link 3
                        </SubA>
                    </DropDownContent>
                </DropDownLi>
            </StyledUl>
        );
    };
}

export default Menu;

结果不一样,主要是因为我不确定如何在styled-component.

如何修复我的 ReactJs 组件Menu代码,使其行为与 W3 示例完全相同?

4

2 回答 2

5

你在翻译代码时犯了一些小错误,但语法和概念都是正确的。您对选择器的使用是正确的:

/* Hovering over current component */
&:hover {
  background-color: red;
}

/* Selecting another styled component                 */
/* calls DropDownContent.toString(), which returns    */
/* the class name of the styled component: .sc-bxivhb */
&:hover ${DropDownContent} {
  display: block;
}

这是一个更正的版本:

import React, { Component } from "react";
import styled from "styled-components";

const StyledUl = styled.ul`
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
`;

const StyledLi = styled.li`
  float: left;
`;

const Dropbtn = styled.div`
  display: inline-block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
`;

const DropDownContent = styled.div`
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
`;

const DropDownLi = styled(StyledLi)`
  display: inline-block;
  &:hover {
    background-color: red;
  }
  &:hover ${DropDownContent} {
    display: block;
  }
`;

const StyledA = styled.a`
  display: inline-block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
  &:hover {
    background-color: red;
  }
`;

const SubA = styled.a`
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
  &:hover {
    background-color: #f1f1f1;
  }
`;

class Menu extends Component {
  handleClick = action => {
    if (!action) return;

    if (this.props.onClick) this.props.onClick(action);
  };

  render = () => {
    return (
      <StyledUl>
        <StyledLi>
          <StyledA onClick={() => this.handleClick("Home")}>Home</StyledA>
        </StyledLi>
        <StyledLi>
          <StyledA onClick={() => this.handleClick("News")}>Home</StyledA>
        </StyledLi>
        <DropDownLi>
          <Dropbtn onClick={() => this.handleClick("DropDown")}>
            DropDown
          </Dropbtn>
          <DropDownContent>
            {" "}
            <SubA onClick={() => this.handleClick("Link1")}>Link 1</SubA>
            <SubA onClick={() => this.handleClick("Link2")}>Link 2</SubA>
            <SubA onClick={() => this.handleClick("Link3")}>Link 3</SubA>
          </DropDownContent>
        </DropDownLi>
      </StyledUl>
    );
  };
}

export default Menu;
于 2019-11-20T22:06:09.937 回答
0

您需要使用类似 scss 的语法。为了像您一样使用伪选择器,hover您需要进行嵌套并使用(&)将引用主选择器的 & 符号。如果您愿意,也可以使用常规class选择器。

您的代码示例:


export const Menu = styled.ul `

  /* main UL component called: "Menu" */
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;

  /* main LI */
  & > li {
    float: left;

    & > a {
      display: inline-block;
      color: white;
      text-align: center;
      padding: 14px 16px;
      text-decoration: none;

      &:hover {
        background-color: red;
      }
    }
  }

  /* dropdown LI */
  & > .dropdown {
      display: inline-block;

      & > .dropdown-content {
        display: none;
        position: absolute;
        background-color: #f9f9f9;
        min-width: 160px;
        box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
        z-index: 1;

        & > a {
          color: black;
          padding: 12px 16px;
          text-decoration: none;
          display: block;
          text-align: left;
          &:hover {
            background-color: #f1f1f1;
          }
        }
      }

      &:hover .dropdown-content {
        display: block
      }
    }
`


而对于 JSX 部分,只需调用 Menu 组件

<Menu>
    <li><a href="#">Home</a></li>
    <li><a href="#">News</a></li>
    <li className="dropdown">
      <a href="#" className="dropbtn">Dropdown</a>
      <div className="dropdown-content">
        <a href="#">Link 1</a>
        <a href="#">Link 2</a>
        <a href="#">Link 3</a>
      </div>
    </li>
</Menu>


这样,我只创建了一个名为Menu的组件,并且所有 JSX 元素都像普通 HTML 一样嵌套。

请参阅代码沙箱中的完整示例:

于 2019-11-20T22:57:06.510 回答