html 如何使用Typescript使标题具有粘性

vsaztqbk  于 2022-12-16  发布在  TypeScript
关注(0)|答案(1)|浏览(130)

我是React开发的新手,我想把头标做得很粘(index.tsx & styles.ts)。
我曾尝试使用React钩:创建一个sticky组件(sticky.tsx和sticky.scss),并通过在index.tsx中插入两行代码import Sticky from ‘./Sticky’<Sticky top={60}><Header /></Sticky>来使用它们,但它不起作用。
如果你有什么想法,欢迎你
请参见下面的代码:
index.tsx

import styled from "styled-components";
import { Link } from "react-router-dom";
import { MenuOutlined } from "@ant-design/icons";

export const HeaderSection = styled("header")`
  padding: 1rem 0.5rem;

  .ant-row-space-between {
    align-items: center;
    text-align: center;
  }
`;

export const LogoContainer = styled(Link)`
  display: flex;
`;

export const NavLink = styled("div")`
  display: inline-block;
  text-align: center;
`;

export const CustomNavLink = styled("div")`
  width: 203px;
  display: inline-block;

  @media only screen and (max-width: 411px) {
    width: 150px;
  }

  @media only screen and (max-width: 320px) {
    width: 118px;
  }
`;

export const ContactWrapper = styled("div")<any>`
  cursor: pointer;
  width: ${(p) => (p.width ? "100%" : "110px")};
  font-weight: 700;
  text-align: center;
  border-radius: 1.25rem;
  display: inline-block;
`;

export const Burger = styled("div")`
  @media only screen and (max-width: 890px) {
    display: block;
  }

  display: none;

  svg {
    fill: #2e186a;
  }
`;

export const NotHidden = styled("div")`
  @media only screen and (max-width: 890px) {
    display: none;
  }
`;

export const Menu = styled("h5")`
  font-size: 1.5rem;
  font-weight: 600;
  text-align: center;
`;

export const CustomNavLinkSmall = styled(NavLink)`
  font-size: 1.2rem;
  color: #18216d;
  transition: color 0.2s ease-in;
  margin: 0.5rem 2rem;

  @media only screen and (max-width: 768px) {
    margin: 1.25rem 2rem;
  }
`;

export const Label = styled("span")`
  font-weight: 500;
  color: #404041;
  text-align: right;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
`;

export const Outline = styled(MenuOutlined)<any>`
  font-size: 22px;
`;

export const Span = styled("span")`
  cursor: pointer;
  transition: all 0.3s ease-in-out;

  &:hover,
  &:active,
  &:focus {
    color: rgb(255, 130, 92);
    text-underline-position: under;
    text-decoration: rgb(255, 130, 92) wavy underline;
  }
`;

styles.ts

import { useState } from "react";
import { Row, Col, Drawer } from "antd";
import { withTranslation } from "react-i18next";
import Container from "../../common/Container";
import { SvgIcon } from "../../common/SvgIcon";
import { Button } from "../../common/Button";
import {
  HeaderSection,
  LogoContainer,
  Burger,
  NotHidden,
  Menu,
  CustomNavLinkSmall,
  Label,
  Outline,
  Span,
} from "./styles";

const Header = ({ t }: any) => {
  const [visible, setVisibility] = useState(false);

  const showDrawer = () => {
    setVisibility(!visible);
  };

  const onClose = () => {
    setVisibility(!visible);
  };

  const MenuItem = () => {
    const scrollTo = (id: string) => {
      const element = document.getElementById(id) as HTMLDivElement;
      element.scrollIntoView({
        behavior: "smooth",
      });
      setVisibility(true);
    };
    return (
      <>
        
        <CustomNavLinkSmall onClick={() => scrollTo("product")}>
          <Span>{t("product")}</Span>
        </CustomNavLinkSmall>
        <CustomNavLinkSmall onClick={() => scrollTo("about")}>
          <Span>{t("about")}</Span>
        </CustomNavLinkSmall>
        <CustomNavLinkSmall onClick={() => scrollTo("mission")}>
          <Span>{t("mission")}</Span>
        </CustomNavLinkSmall>
        <CustomNavLinkSmall
          style={{ width: "180px" }}
          onClick={() => scrollTo("contact")}
        >
          <Span>
            <Button>{t("Contact")}</Button>
          </Span>
        </CustomNavLinkSmall>
      </>
    );
  };

  return (
    <HeaderSection>
      <Container>
        <Row justify="space-between">
          <LogoContainer to="/" aria-label="homepage">
            <SvgIcon src="logo.svg" width="101px" height="64px" />
          </LogoContainer>
          <NotHidden>
            <MenuItem />
          </NotHidden>
          <Burger onClick={showDrawer}>
            <Outline />
          </Burger>
        </Row>
        <Drawer closable={false} visible={visible} onClose={onClose}>
          <Col style={{ marginBottom: "2.5rem" }}>
            <Label onClick={onClose}>
              <Col span={12}>
                <Menu>Menu</Menu>
              </Col>
              <Col span={12}>
                <Outline />
              </Col>
            </Label>
          </Col>
          <MenuItem />
        </Drawer>
      </Container>
    </HeaderSection>
  );
};

export default withTranslation()(Header);

sticky.tsx

import React, { useState, useEffect, useRef } from 'react';

import './Sticky.scss';

interface StickyProps {
    child: React.ReactChild,
    top: number,
}

const  Sticky: React.FunctionComponent<StickyProps> = (child, top) => {
  const [isSticky, setSticky] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    // Add scroll event when the component is loaded
    window.addEventListener('scroll', handleScroll);
    return () => {
    // Remove scroll event after the component is unmount,
    // like componentWillUnmount()
      window.removeEventListener('scroll', () => handleScroll);
    };
    // Here, we set useEffect() arguments as empty array.
    // This means useEffect() will only run once after component loaded
  }, []);

  const handleScroll = () => {
    // Make sure ref has current attibute and getBoundingClientRect function
    // otherwise, it could cause getBoundingClientRect undefined error.
    if (ref && ref.current && ref.current.getBoundingClientRect()) {
        // Then, we compare the distance of the ref component to the top
        // with top value we set. If less than, we set isStick ture.
        setSticky(ref.current.getBoundingClientRect().top <= top);
    }
  };

  return (
      <div className={`sticky__wrapper ${isSticky && 'sticky'}`} ref={ref}>
        <div className="sticky--inner">
            {child}
        </div>
      </div>
  );
};

export default Sticky

sticky.scss

.sticky__wrapper {
    position: relative;
    // height: 4rem; /* probably you need to set height value for wrapper */
  }
  
.sticky .sticky--inner {
    position: fixed;
    // top: 0; 
    z-index: 1;
}
p1iqtdky

p1iqtdky1#

请注意,您混淆了帖子中的文档名称。
转到:源文件\组件\标题\样式.ts
查找行:

export const HeaderSection = styled("header")`
  padding: 1rem 0.5rem;

并在下面添加:

position: sticky;
  top: 0;
  background-color: white;
  z-index: 1;

要获得:

export const HeaderSection = styled("header")`
  padding: 1rem 0.5rem;
  position: sticky;
  top: 0;
  background-color: white;
  z-index: 1;
  .ant-row-space-between {
    align-items: center;
    text-align: center;
  }

`;

根据需要调整background-color: yourfavoritecolor;
z-index: 1;会将HeaderSection放在最前面。否则,您的内容将滚动到HeaderSection上。

相关问题