【问题标题】:React toggle active class on click of anchor using Gatsby Js使用 Gatsby Js 在单击锚点时反应切换活动类
【发布时间】:2018-09-14 14:41:04
【问题描述】:

我正在使用 GatsbyJs 并试图完成一个活动类切换。我有一个简单的组件,它由一个带有跨度的锚标记组成。我想通过切换锚点击时上的活动类来更改一些css。到目前为止,这是我的代码,我也在使用样式组件。我在下面的损坏代码部分尝试了一些 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>

【问题讨论】:

  • 你能发布 #nav-toggle 被渲染的反应代码吗?
  • 好的,我添加了上面呈现的内容。我还修复了菜单组件中缺少导航切换 ID 的内容。但是,损坏的代码部分甚至不允许应用程序运行。如果我删除它,应用程序就会运行并且一切正常。
  • 我看到了问题,您需要在样式组件中的“.active span”之前添加“&”。像 &.active span ...
  • 你得到的错误是什么?

标签: javascript css reactjs styled-components gatsby


【解决方案1】:

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

我喜欢这个包来处理您处理基于道具或状态的多个类的样式的情况:https://github.com/JedWatson/classnames

为了清楚这个答案,我简化了样式,并假设 menu 是一个全局类,你也想应用。

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 加嵌套。

与号 (&) 被我们为该样式组件生成的唯一类名替换,从而可以轻松实现复杂的逻辑。

但是,您可以通过充分利用styled components 功能在不使用classnames 的情况下实现相同的效果。看看这个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>
  );
}

【讨论】:

  • 我收到以下错误 Failed prop type: Invalid prop children` 提供给 TemplateWrapper,需要一个 ReactNode。`
  • 这很奇怪,正如docs 中所述,node 指的是“可以渲染的任何东西:数字、字符串、元素或包含这些类型的数组(或片段)。”。所以它是children 的正确道具。你提供了什么children?更具体地说 你在这里有什么? :D
  • 嗯,我在任何地方都没有&lt;TemplateWrapper&gt;stuff goes here&lt;/TemplateWrapper&gt;。我尝试自己添加一个&lt;TemplateWrapper/&gt;,但我得到了同样的错误。我已经在更新部分的上述答案中准确地添加了我在代码中的内容。
  • 我正在使用 Gatsby js,这是我的 layout/index.js 文件,所以我没有在任何地方使用 。希望我们能解决这个问题。
  • 我唯一能想到的是children 应该是我的页面呈现的地方。我有一个layout/index.js 文件,这是我上面的代码,然后我有一个pages/index.js, pages/portfolio.js,它们分别在children 部分内呈现,只是想知道这是否与 Gatsby js 相关。
【解决方案2】:

您可以使用组件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" />

【讨论】:

  • 谢谢,我一回到我的电脑就试试这个。
  • 如何将它与我当前的组件集成?我已经在导出我的模板包装器了,我要导出两次还是很困惑。
  • 你应该修改Menu组件而不是TemplateWrapper 来实现这个功能。
  • 我不能这样使用样式化组件吗,我正在设置这样const Menu = styled.a' color:blue';样式化组件我该怎么做?
猜你喜欢
  • 1970-01-01
  • 2014-06-16
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多