首页 > 解决方案 > 我是否正确使用样式组件?

问题描述

我的 App.js 开始看起来很长,我开始怀疑我是否按照预期的方式使用 styled-components。

import React, { Component } from "react";
import "./App.scss";
import styled, { keyframes } from "styled-components";
import { TweenMax, TweenLite, Power2, TimelineLite } from "gsap";
import NameSvg from "./name";
import Nav from "./Nav";
import Player from "./Player";

class App extends Component {
  nav = null;
  hero = null;
  welcome = null;
  wrapper = null;
  scroll = null;
  name = null;
  tl = new TimelineLite({ paused: true });
  lis = [];
  welcomeTxt = [];

  changePlayingState = () => {
    this.setState({ playing: !this.state.playing });
  };

  state = {
    liText: [{ li: "My Work", id: 1 }, { li: "About Me", id: 2 }],
    welcomeTxt: [{ word: "Hello", id: 1 }, { word: "I'm", id: 2 }],
    playing: false
  };

  componentDidMount() {
    this.tl
      .staggerTo(this.welcomeTxt, 0.9, { opacity: 1, y: 70 }, 0.1)
      .staggerTo(
        this.welcomeTxt,
        0.9,
        { visibility: "visible", opacity: 0, delay: 0.5 },
        "prev"
      )
      .to(this.name, 0.9, { y: 350, x: -400 }, "prev+=.5")
      .to(this.nav, 0.9, { opacity: 1 }, "prev+=.5")
      .to(this.hero, 0.9, { opacity: 1 }, "p rev+=.9")
      .staggerTo(this.lis, 0.9, { opacity: 1, x: 20 }, "prev+=.9")
      .to(this.music, 0.9, { opacity: 1 }, "prev+=2")
      .to(this.scroll, 0.9, { visibility: "visible" }, "prev+=2");

    this.tl.play();
  }

  render() {
    return (
      <Wrapper ref={div => (this.wrapper = div)}>
        <Nav ref={div => (this.nav = div)}>
          Logo
          <ul>
            {// map through the elements
            this.state.liText.map((element, index) => (
              <a href="#">
                <li key={index} ref={li => (this.lis[index] = li)}>
                  {element.li}
                </li>
              </a>
            ))}
          </ul>
          <Logo />
        </Nav>
        <Welcome ref={div => (this.welcome = div)}>
          {// map through the elements
          this.state.welcomeTxt.map((element, index) => (
            <div
              className={`welcome${index}`}
              key={index}
              ref={div => (this.welcomeTxt[index] = div)}
            >
              {element.word}
              <br />
            </div>
          ))}
          <Name ref={div => (this.name = div)}>
            <NameSvg className="namesvg" />
          </Name>
        </Welcome>

        <Music ref={div => (this.music = div)}>
          <ToolTip>
            pst..could i interest you in some music for your stay?
            <button className="noThanks">No..thanks</button>
          </ToolTip>
          <a href="#" onClick={this.changePlayingState}>
            {this.state.playing ? (
              <img
                src="https://img.icons8.com/material/48/000000/circled-pause.png"
                key={"pause"}
              />
            ) : (
              <img
                src="https://img.icons8.com/material-rounded/48/000000/circled-play.png"
                alt="play button"
                key={"play"}
                className="playButton"
              />
            )}
          </a>
          {this.state.playing ? <Player playing={this.state.playing} /> : null}
        </Music>

        <Scroll ref={div => (this.scroll = div)}>
          <div className="one" />
          <div className="two" />
          <div className="three" />
        </Scroll>
        <Enter />
        <Hero ref={div => (this.hero = div)} className="hero" />
      </Wrapper>
    );
  }
}

export default App;

const building = keyframes`
  0% {
    left: 0;
    width:0;
    opacity:1;
  } 
  50%{
    left:0;
    width:70%;
    opacity:.7
  }
  100% {
    left: 70%;
    width:0;
    opacity:0;
  }
`;

const Wrapper = styled.div`
  display: grid;
  background: #f8f8f8;
  height: 100vh;
  grid-template-columns: repeat(12, 1fr);
  grid-template-rows: repeat(12, 1fr);
  font-family: "Roboto Condensed", sans-serif;
  transform: translateX(-15px);
  overflow: hidden;
`;

const Logo = styled.div``;

const appear = keyframes`
  0% {
    opacity:0
  } 
  50%{
    opacity:.7
  }
  100% {
    opacity:1;
  }
`;

const Name = styled.div`
  position:absolute;
  top:-6%;
  left:-12%;
  height:300%;
  grid-column: 1/5;
  grid-row: 9/13;
  z-index: 3;
  }
`;

const Music = styled.div`
  opacity: 0;
  grid-column: 11/13;
  grid-row: 1/2;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  margin-top: 3em;
  position: relative;
`;

const ToolTip = styled.div`
  ${"" /* visibility: hidden; */}
  position: absolute;
  height: auto;
  padding: 0.3em;
  width: auto;
  bottom: 5.5em;
  border: 0.3px solid black;
  left: -1em;
`;

const Scroll = styled.div`
  visibility: hidden;
  grid-column: 11/13;
  grid-row: 6/9;
  display: flex;
  ${"" /* flex-direction: column; */}
  justify-content: center;

  & .one {
    height: 10px;
    width: 10px;
    background: black;
    border-radius: 50%;
    margin-right: 0.5em;
  }

  & .two,
  .three {
    height: 10px;
    width: 10px;
    background: transparent;
    border: 0.5px solid black;
    border-radius: 50%;
    margin-right: 0.5em;
  }
`;

const Enter = styled.div`
  opacity: 0;
  background: white;
  grid-column: 11/13;
  grid-row: 9/13;
`;

const Hero = styled.div`
  opacity: 0;
  grid-column: 4/12;
  grid-row: 1/12;
  transform: translate(-20%, 20%);

  &:before {
    content: "";
    position: absolute;
    background: rgba(0, 0, 0, 0.9);
    height: 100%;
    width: 0%;
    display: block;
    animation: ${building} 1s;
    animation-delay: 3s;
    animation-fill-mode: forwards;
  }
`;

const Welcome = styled.div`
  position: relative;
  transform: translate(100px, 100px);
  font-family: Neou-Thin;
  font-size: 100px;
`;

我想知道如何将它们分支到他们自己的文件中......我正在使用 GSAP 进行动画制作,当我尝试将内容分支到他们自己的文件中时,动画要么停止工作,要么出现错误,像“不能补间空”之类的东西

我试图将导航分支到它自己的文件中的一个例子:

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

class Nav extends Component {
  render() {
    return <Navigation />;
  }
}

export default Nav;

const Navigation = styled.div`
  opacity: 0;
  color: black;
  padding: 2em;
  grid-column: 1 / 3;
  grid-row: 1/6;
  font-family: Neou-Bold;

  & ul {
    list-style: none;
    padding: 0;
    margin-top: 3em;
    font-size: 1.1em;
  }

  & a {
    text-decoration: none;
    color: black;
  }
  & li {
    opacity: 0;
    padding-bottom: 0.5em;
  }
`;

当我这样做时,动画不起作用。

标签: javascriptreactjsstyled-componentsgsap

解决方案


代码拆分

考虑到何时将组件拆分为新文件,您可能应该经常这样做,无论是为了可读性还是代码重用。你App.js的确实有点偏大。据我所知,您使用styled-components得很好,但是当您在一个地方有这么多文件时,建议将它们放在单独的文件中。


GSAP 问题

问题似乎在于您如何尝试导出styled-components. 提取到新文件后没有动画的原因Nav似乎是因为您将它不必要地包装在一个额外的组件中。实际上只需执行以下操作就足够了:

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

const Nav = styled.div`
  opacity: 0;
  color: black;
  padding: 2em;
  grid-column: 1 / 3;
  grid-row: 1/6;
  font-family: Neou-Bold;

  & ul {
    list-style: none;
    padding: 0;
    margin-top: 3em;
    font-size: 1.1em;
  }

  & a {
    text-decoration: none;
    color: black;
  }
  & li {
    opacity: 0;
    padding-bottom: 0.5em;
  }
`;

export default Nav;

Nav当我尝试如上图所示导出组件时,动画有效。


推荐阅读