简体   繁体   English

在React中单击组件时将类添加到同级中

[英]Add class to siblings when Component clicked in React

I'm working on building my portfolio using React.js. 我正在使用React.js构建我的投资组合。 In one section, I have four components laid out in a grid. 在一节中,我将四个组件布置在一个网格中。 What I want to do achieve is when one component is clicked, a css class is added to the siblings of this component so that their opacity is reduced and only the clicked component remains. 我要做的是单击一个组件时,将一个CSS类添加到该组件的同级中,以降低其不透明度,仅保留被单击的组件。 In jQuery, it would be something like $('.component').on('click', function(){ $(this).siblings.addClass('fadeAway')}). 在jQuery中,它类似于$('。component')。on('click',function(){$(this).siblings.addClass('fadeAway')})。 How can I achieve this effect? 我怎样才能达到这种效果? Here is my code, thanks in advance for any and all help! 这是我的代码,在此先感谢您提供的所有帮助!

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} />
      })
    )
  }
}

A working example for this problem could look something like this, with a marginally more complex initialization array: 这个问题的可行示例可能看起来像这样,带有稍微复杂一些的初始化数组:

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} />
      });
    );
  }
}

Then you would just add a ternary, like so, to the Child component: 然后,您只需向Child组件添加一个三元,就像这样:

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

This adds a bit more boilerplate than other examples, but it's extremely brittle to tie business logic to the text inside a component, and a stronger solution requires a stronger piece of identification, like an ID or class on the rendered DOM element. 与其他示例相比,这增加了一些样板,但是将业务逻辑绑定到组件内部的文本非常脆弱,并且更强大的解决方案需要更强大的标识,例如呈现的DOM元素上的ID或类。 This solution also, if you so wish, easily allows you to expand your logic so that more than one element can remain at maximum opacity at once. 如果您愿意的话,此解决方案还可以轻松地扩展您的逻辑,以使多个元素可以一次保持最大不透明度。

I would simply store in state index of selected item, and then pass fadeAway prop into Child component defined as 我只是将其存储在所选项目的状态索引中,然后将fadeAway传递fadeAway定义为

fadeAway={this.state.selectedIndex !== index}

After that you only need to set a fade-away class in Child based on this.prop.fadeAway and define necessary CSS rules. 之后,您仅需要基于this.prop.fadeAway在Child中设置一个fade-away类,并定义必要的CSS规则。

Here is how it could look in your case: 这是您情况下的外观:

 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> 

You can achieve that using using a toggle variable : 您可以使用切换变量来实现:

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

I perfer use state like currentWord to save the word was clicked in Parent component, presudo code is like below: 我认为使用诸如currentWord类的currentWord来保存在Parent组件中单击的单词,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} />
      })
    )
  }
}

And in Child component 在子组件中

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>
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM