【问题标题】:Add class to siblings when Component clicked in React在 React 中单击组件时向兄弟姐妹添加类
【发布时间】:2017-09-12 09:37:51
【问题描述】:

我正在使用 React.js 构建我的作品集。在一个部分中,我将四个组件布置在一个网格中。我想要实现的是,当单击一个组件时,将一个 css 类添加到该组件的兄弟姐妹中,以降低它们的不透明度,并且只保留单击的组件。在 jQuery 中,它类似于 $('.component').on('click', function(){ $(this).siblings.addClass('fadeAway')})。我怎样才能达到这个效果?这是我的代码,在此先感谢您的帮助!

class Parent extends Component{
  constructor(){
    super();
    this.state = {fadeAway: false}
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick(){
    //Add class to siblings
  }
  render(){
    const array = ["Hello", "Hi", "How's it going", "Good Times"]
    return(
      array.map(function(obj, index){
        <Child text={obj} key={index} onClick={() => this.handleClick} />
      })
    )
  }
}

【问题讨论】:

    标签: javascript html css reactjs components


    【解决方案1】:

    这个问题的一个工作示例可能看起来像这样,具有稍微复杂的初始化数组:

    class Parent extends Component{
      constructor(){
        super();
        this.state = {
          elements: [
            {
              id: "hello",
              text: "Hello",
              reduced: false,
            },
    
            {
              id: "hi",
              text: "Hi",
              reduced: false,
            }
    
            {
              id: "howsItGoing"
              text: "How's it going",
              reduced: false,
            }
    
            {
              id: "goodTimes",
              text: "Good Times",
              reduced: false,
            }
          ],
        }
    
        this.handleClick = this.handleClick.bind(this)
      }
    
      handleClick(e){
        // copy elements from state
        const elements = JSON.parse(JSON.stringify(elements));
        const newElements = elements.map(element => {
          if (element.id === e.target.id) {
            element.reduced = false;
          } else {
            element.reduced = true;
          }
        });
    
    
        this.setState({
          elements: newElements,
        });
      }
    
      render(){
        return(
          this.state.elements.map(function(obj, index){
            <Child
              id={obj.id}
              text={obj.text}
              reduced={obj.reduced}
              key={index}
              onClick={() => this.handleClick} />
          });
        );
      }
    }
    

    然后您只需像这样向Child 组件添加一个三元组:

    <Child
      id={this.props.id}
      className={this.props.reduced ? "reduced" : ""} />
    

    这比其他示例添加了更多样板文件,但是将业务逻辑与组件内的文本联系起来非常脆弱,并且更强大的解决方案需要更强大的标识,例如呈现的 DOM 元素上的 ID 或类。如果您愿意,此解决方案还可以让您轻松扩展逻辑,以便多个元素一次保持最大不透明度。

    【讨论】:

    • 这个解决方案实际上帮助最大。起初,我所做的事情似乎有点健壮,但你真的很好地解释了它,现在对我来说完全有意义。我不得不稍微调整一下 handleClick 函数,并且不需要使用 JSON.parse,但总体概念有效,我实现了最终目标。谢谢!! @furkle
    • @IanSpringer 很高兴为您提供帮助!
    【解决方案2】:

    我将简单地存储在所选项目的状态索引中,然后将fadeAway prop 传递给定义为

    的子组件
    fadeAway={this.state.selectedIndex !== index}
    

    之后你只需要基于this.prop.fadeAway在Child中设置一个fade-away类并定义必要的CSS规则。

    以下是您的情况:

    class Parent extends React.Component{
      constructor () {
        super();
        this.state = {selectedIndex: null}
      }
      handleClick (selectedIndex) {
        this.setState({ selectedIndex })
      }
      render () {
        const array = ["Hello", "Hi", "How's it going", "Good Times"]
        return (
          <div>
            {array.map((obj, index) => {
              const faded = this.state.selectedIndex && this.state.selectedIndex !== index
              return <Child 
                text={obj} 
                fadeAway={faded}
                key={index} 
                onClick={() => this.handleClick(index)} />
            })}
          </div>  
        )
      }
    }
    
    class Child extends React.Component {
      render () {
        return (
          <h2
            onClick={this.props.onClick}
            className={this.props.fadeAway ? 'fade-away' : ''}>
            {this.props.text}
          </h2>  
        ) 
      }
    }
    
    ReactDOM.render(
      <Parent />,
      document.body
    );
    .fade-away {
      opacity: 0.3;
    }
    <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>

    【讨论】:

    • 谢谢,这似乎很接近。但是,当页面呈现时,我希望所有组件都具有完全不透明度。当一个被点击时,其他的应该会失去它们的不透明度。此解决方案将一个组件设置为在页面加载时处于活动状态,此时它们都应该处于活动状态,直到单击一个组件。有什么建议吗?
    • @IanSpringer 当然,只需将默认的selectedIndex 设为null 并在const faded = this.state.selectedIndex &amp;&amp; this.state.selectedIndex !== index 中检查它。查看演示。
    【解决方案3】:

    您可以使用切换变量来实现:

    handleClick(){
      this.setState({fadeAway} => ({
        fadeAway: ! fadeAway
      )};
    }
    ...
    <Child
      text={obj}
      key={index}
      onClick={() => this.handleClick}
      className={this.state.fadeAway? 'class1' : 'class2'}/>
    

    【讨论】:

    • 谢谢,但这个解决方案似乎切换了目标组​​件的类。我需要为单击的组件的兄弟姐妹添加一个新类。
    【解决方案4】:

    我更喜欢使用currentWord这样的状态来保存在父组件中被点击的单词,presudo代码如下:

    class Parent extends Component {
      constructor(){
        super();
        this.state = {
          fadeAway: false,
          currentWord: ''
        };
        this.handleClick = this.handleClick.bind(this)
      }
      handleClick(currentWord){
        this.setState({
          currentWord: currentWord,
        });
      }
      render(){
        const array = ["Hello", "Hi", "How's it going", "Good Times"]
        const currentWord = this.state.currentWord;
        return(
          array.map(function(obj, index){
            <Child currentWord={currentWord} text={obj} key={index} onClick={() => this.handleClick} />
          })
        )
      }
    }
    

    在子组件中

    class Child extends Component {
      // some other code
    
      handleClick(e) {
        this.props.handleClick(e.target.value);
      }
    
      render() {
        const isSelected = this.props.text === this.props.currentWord;
        // use isSelected to toggle className
    
        <div
          onClick={this.handleClick.bind(this)}
        >{this.props.text}
        </div>
      }
    }
    

    【讨论】:

    • 您将 prop 传递为 currentWord,但在子组件中将其引用为 CurrentWord
    猜你喜欢
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多