使用 Gatsby Js 在单击锚点时反应切换活动 class

React toggle active class on click of anchor using Gatsby Js

我正在使用 GatsbyJs 并试图完成一个活动的 class 切换。我有一个简单的组件,由一个内部带有 span 的锚标记组成。我想更改一些 css,方法是在单击 时在锚点 上切换活动 class。到目前为止,这是我的代码,我也在使用样式组件。我在下面的损坏代码部分尝试了一些 vanilla js,这显然不起作用因此损坏了代码。

提前致谢

样式

const Menu = styled.a`
  position: absolute;
  cursor: pointer; padding: 10px 35px 16px 0px;
  span, span:before, span:after{
    cursor: pointer;
    border-radius: 1px;
    height: 5px;
    width: 35px;
    background: #000000;
    position: absolute;
    display: block;
    content: '';
    transition: all 200ms ease-in-out;
  }
  span:before{
    top: -10px; 
  }
  span:after{
    bottom: -10px; 
  }
  .active span{
    background-color: transparent;
  }
  .active span:before, .active span:after{
    top:0;
  }
  .active span:before{
    transform: rotate(45deg);
  }
  .active span:after{
    transform: rotate(-45deg);
  }
`

组件

const TemplateWrapper = ({ children }) => (
  <div>
    <Wrapper>
      <Menu id="nav-toggle" className="menu"><span></span></Menu>
      {children()}
    </Wrapper>       
  </div>
)

TemplateWrapper.propTypes = {
  children: PropTypes.func,
}

export default TemplateWrapper

破损代码

document.querySelector( "#nav-toggle" )
  .addEventListener( "click", function() {
    this.classList.toggle( "active" );
  });

这是呈现的html

<a class="menu sc-bwzfXH SqHLW" id="nav-toggle"><span></span></a>

您可以使用组件 state 来管理它。 代码将如下所示:

更新: 将逻辑移至 Menu 组件,因为将其放置在那里更有意义。下面的工作示例

class Menu extends React.Component {

  constructor(props) {
    super(props);
    
    this.menuClick = this.menuClick.bind(this);
    this.state = {
      menuClass: '',
    }
  }
  
  menuClick(e) {
    const menuClass = this.state.menuClass === '' ? 'active' : '';
    this.setState({ menuClass });
  }
  
  render() {
    const {children, id} = this.props;
    const menuClassName = `menu sc-bwzfXH SqHLW nav-toggle ${this.state.menuClass}`;
    
    return (<a className={menuClassName} id={id} onClick={this.menuClick}>{children}</a>);

  }
}

ReactDOM.render(<Menu><span>Test link</span></Menu>,  document.getElementById('menu'))
.menu {
  font-weight: bolder;
  color: blue;
 }
 
.active{
  color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="menu" />

好的,你可以看这里 REACT - toggle class onclick 。有几个答案显示了如何实现这一点,但是当您想要使用多个答案时,事情会变得更加混乱 class.

我喜欢这个包来处理你根据道具或状态处理多个 classes 样式的情况:https://github.com/JedWatson/classnames.

为了这个答案的清晰起见,我简化了样式,并假设 menu 是全局的 class,你也想申请。

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import styled from 'styled-components';

const Wrapper = styled.div``;

const Menu = styled.a`
  span {
    color: green;
  }
  &.active span {
    color: blue;
  }
`;

class TemplateWrapper extends Component {
  state = {
    isActive: false
  };

  handleClick = () => {
    this.setState(state => ({ isActive: !state.isActive }));
  };

  render() {
    const menuClass = classNames({
      menu: true,
      active: this.state.isActive
    });

    return (
      <Wrapper>
        <Menu id="nav-toggle" className={menuClass} onClick={this.handleClick}>
          <span>Test</span>
        </Menu>
        {this.props.children}
      </Wrapper>
    );
  }
}

TemplateWrapper.propTypes = {
  children: PropTypes.node
};

TemplateWrapper.defaultProps = {
  children: null
};

export default TemplateWrapper;

注意 .active 之前的符号 (&)。如 docs 中所述,styled components 支持所有 CSS 加嵌套。

Ampersands (&) get replaced by our generated, unique classname for that styled component, making it easy to have complex logic.

但是,您可以在没有 classnames 的情况下充分利用文档的 styled components functionality. Take a look at this section 来达到相同的效果。

需要进行一些更改:

const Menu = styled.a`
  span {
    color: ${props => (props.active ? 'blue' : 'green')};
  }
`;

呈现方法如下所示:

render() {
  return (
    <Wrapper>
      <Menu id="nav-toggle" className="menu" active={this.state.isActive} onClick={this.handleClick}>
        <span>Test</span>
      </Menu>
      {this.props.children}
    </Wrapper>
  );
}