【问题标题】:Toggling font awesome Icon using React使用 React 切换字体真棒图标
【发布时间】:2019-09-04 19:40:18
【问题描述】:

我想在点击时切换一个 fontAwesome 图标类名。单击时,图标应更改颜色并调用将对象添加到服务器中收藏列表的服务(因此,我使用 e.currentTarget 的原因:我需要记住单击了哪个图标)。此代码在第一次单击时有效,但在第二次单击时无法将类改回(进行检查,它说 FA 的类名等于“对象对象”)。知道如何解决吗?

    <FontAwesomeIcon onClick={this.ToggleClass} size={"sm"} icon={faHeart} />

    ToggleClass = (e) => {
      const heart = {
        color: "#E4002B",
      }

      const clicked = {
        color: "#E4002B",
        background: "red"
      }

      if (e.currentTarget.className.baseVal != heart && e.currentTarget.className.baseVal != clicked) {
        return e.currentTarget.className.baseVal === clicked;
#Callservicehere
      }
      else if (e.currentTarget.className.baseVal === clicked) {
        e.currentTarget.className.baseVal = heart;
#callservicehere
      }
    }

【问题讨论】:

  • 让我们看看ToggleClass 的定义。
  • 抱歉,粘贴的时候忘记改名字了。请查看更新版本。
  • 使用 e.currentTarget 有点矫枉过正。您可以只在 css 中创建类而不是 css 的变量,并在单击时切换状态。根据状态切换图标。你可以看看这个链接toggle icon
  • 这不起作用,因为我有几个图标,我只想使用一种方法。因此 e.currentTarget
  • 每次调用该函数时,您都会创建新对象,因此比较永远不会正确。 “旧”对象永远不会与“新”对象相同,即使它包含相同的元素。

标签: reactjs


【解决方案1】:

你还没有考虑 React :)

访问事件目标并命令式地操作 DOM 会绕过 React 的渲染 - 您可能只是使用 jQuery。并不是说这有什么不好,但这不是在 React 中处理事情的正确方法。

在 React 中,如果您需要更改 DOM 以响应用户交互,请在 render 方法中进行,即根据组件的当前状态或 props 输出不同的 JSX。

【讨论】:

    【解决方案2】:

    这里有几件事可能会有所帮助:

    1. clickedheart 都是对象,这意味着如果不使用深度比较方法就无法比较它们。
    var a = { id: 1 }
    var b = { id: 1 }
    
    console.log(a == b)    //false
    console.log(a === b)   //false
    
    1. 如果要比较它们,可以使用toString() 方法将它们都转换为字符串
    heart.toString() === clicked.toString() 
    
    1. 在您的第一个 if 条件中,您似乎正在返回一个真/假值,而不是为您的目标分配所需的类名。
    return e.currentTarget.className.baseVal === clicked // true/false
    
    
    e.currentTarget.className.baseVal = clicked // assigned
    
    1. 您还可以采用将类名保留为字符串并将样式对象添加到 css 中的方法
    class MysteryComponent extends React.Component {
      state = {
        className: 'heart'
      }
    
      toggleClass = (e) => {
        if (this.state.className === 'heart') {
          this.setState({ className: 'clicked' })
        } else if (this.state.className === 'clicked') {
          this.setState({ className: 'heart' })
        }
      }
    
      render() {
        return (
          <div className={this.state.className}>
            <FontAwesomeIcon onClick={this.toggleClass} size={"sm"} icon={faHeart} />
          </div>
        )
      }
    }
    
    // css 
    .heart {
      color: "#E4002B";
    }
    
    .clicked {
      color: "#E4002B";
      background: "red";
    }
    

    【讨论】:

    • 感谢您的回复。不幸的是,我有许多图标调用了一项服务,将特定项目添加到收藏夹列表中。所以记住点击了哪个图标很重要。此代码将填充所有图标,这并不是我真正想要的。
    【解决方案3】:

    我明白了。您希望在用户单击时填充/取消填充心脏的颜色。结果不符合您的期望的原因是 event.targets 使用 FontAwesome 时特别​​时髦。您可能认为您正在单击它,但它以一种方式操纵 DOM,当您尝试提取 className 时,它​​的值通常是不一致的。

    这就是为什么每个人都建议你使用 React 的状态。确定元素样式的逻辑现在更多地由组件本身而不是 FontAwesome 库控制。考虑下面的代码,我们只关心项目是否被点击,而不关心它最初有什么类。

    class Example extends React.Component{
        state = {
            clicked: false
        }
    
        handleOnCLick = () => {
            this.setState({
                clicked: !this.state.clicked
            })
        }
    
        render(){
    
            var clicked = this.state.clicked
    
            return(
            <button onClick={this.handleOnClick}>
                <i
                    class={ clicked ? "fas fa-heart" : "fas fa-circle"}
                </i>
            </button>
    
            )
        }
    }
    

    【讨论】:

    • 感谢您的回复。不幸的是,我有许多图标调用了将特定项目添加到收藏列表的服务。所以记住点击了哪个图标很重要。此代码将填充所有图标,这并不是我真正想要的。
    • 你可以使用多个状态来跟踪它。
    猜你喜欢
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 2014-06-09
    • 2014-01-16
    • 2020-09-11
    相关资源
    最近更新 更多