【问题标题】:Toggle background color of list on click react.js在单击 react.js 时切换列表的背景颜色
【发布时间】:2015-10-03 11:13:45
【问题描述】:

我正在尝试创建一个具有以下功能的列表。

  1. 悬停时更改 listItem 的背景颜色。
  2. 单击时更改列表项的背景颜色。
  3. 在单击的元素之间切换背景颜色。[即列表中只有一个元素可以具有 clicked 属性]

我已经执行了 onhover 1 和 2 功能,但我无法实现第三个功能。请帮我解决这个问题。

提前致谢。

/** @jsx React.DOM */

   'use strict'

    var React = require('react')


    var ListItem = React.createClass({

        getInitialState: function() {
            return  {hover_flag: false, click_flag: false}
        },

        hoverEvent: function() {
            this.setState({hover_flag: !this.state.hover_flag})
        },

        clickEvent: function(){
            this.setState({click_flag: true})
        },

        render: function() {
            var liStyle = {
                /* some more class properties */
                background: '#cc181e',
            }

            if(this.state.hover_flag || this.state.click_flag) {
                liStyle['background'] = '#880000'
            }

            if(this.state.click_flag) {
                liStyle['background'] = '#880000'           
            }

            return (
                <li onClick={this.clickEvent} onMouseEnter={this.hoverEvent} onMouseLeave={this.hoverEvent} style={liStyle} key={this.props.name}>{this.props.name}</li>
            )
        }

    })


    module.exports = React.createClass({

        render: function() {

            var ulStyle = {
                padding: '0px',
                margin: '20px',
            }

            var link = {
                textDecoration: 'none',
                color: 'white',
                cursor: 'pointer'       
            }


            var list = this.props.data.map(function(data) {
                /*List of li elements */
                return <ListItem name={data.name} />
            })

            return (

                <ul style={ulStyle}>
                    {list}
                </ul>

            )
        }

    });

【问题讨论】:

    标签: javascript jquery reactjs


    【解决方案1】:

    由于只有一个选定项,因此父组件可以使用选定项索引保持状态。

    父组件

    getInitialState: function(){
      return {selectedItem : null, items: this.props.data};
    }
    

    将渲染方法更改为类似这样(注意发送到 ListItem 组件的 isSelected 属性)

    var selectedItem = this.state.selectedItem;
    var list = this.state.items.map(function(data) {
      /*List of li elements */
      return <ListItem name={data.name} onSelect={this.onSelectHandler} isSelected={selectedItem === data.id} key={data.id}/> // <--- I would suggest having a unique ID
    });
    

    让我们稍后实现 onSelectHandler。

    列表项

    在定义中将 prop isSelected 转移到 ListItem 的状态

    getInitialState: function(){
      return  {hover_flag: false, click_flag: this.props.isSelected} // <---- notice the change here
    }
    

    现在修改 clickEvent 并触发 ListItem 的 onSelect 属性并发送单击的 ListItem 的名称(我也建议在这里使用唯一 ID)

    clickEvent: function(){
      this.setState({click_flag: true});
      this.props.onSelect(this.props.name); // <--- I would suggest sending ID
    }
    

    现在让我们为父组件实现 onSelectHandler

    onSelectHandler: function(childItemID){
      this.setState({selectedItem: childItemID});
    }
    

    希望这是有道理的

    【讨论】:

      【解决方案2】:

      在查看任何代码之前,请考虑问题的实际原因。在您当前的实现中,每个 ListItem 都维护自己的 click_flag 状态。单击一个 ListItem 时,它会将自己的 click_flag 设置为 true,但这不会触发其他 ListItem 将自己的 click_flag 重置为 false。这就是问题的原因。解决方案是将 click_flag 作为 props 从父级传递给每个 ListItem。父母有责任确保只有 ListItem 将 prop 设为 true,而其他的则为 false。同样,ListItem 有责任通过从父级传递下来的回调属性通知父级。

      所以,ListItem 看起来像:

      var ListItem = React.createClass({
          propTypes: {
              onClick: React.PropTypes.func.isRequired,
              isSelected: React.PropTypes.bool
          },
          getDefaultProps: function() {
              return {
                  isSelected: false
              };
          },
          getInitialState: function() {
              return {
                  hover_flag: false
              };
          },
          hoverEvent: function() {
              this.setState({hover_flag: !this.state.hover_flag});
          },
          render: function() {
              var liStyle = {
                  background: '#cc181e'
              };
              if (this.props.isSelected || this.state.hover_flag) {
                  liStyle['background'] = '#880000';
              }
              return (
                  <li
                      onClick={this.props.onClick}
                      onMouseEnter={this.hoverEvent}
                      onMouseLeave={this.hoverEvent}
                      style={liStyle}>{this.props.name}
                  </li>
              );
          }
      });
      

      而且,父级可能如下所示:

      module.exports = React.createClass({
          getInitialState: function() {
              return {
                  selectedItem: null
              };
          },
          clickHandler: function(idx) {
              this.setState({selectedItem: idx});
          },
          render: function() {
              var ulStyle = {
                  padding: '0px',
                  margin: '20px'
              };
              var items = this.props.data.map(function (item, idx) {
                  var is_selected = this.state.selectedItem == idx;
                  return <ListItem
                      key={item.name}
                      name={item.name}
                      onClick={this.clickHandler.bind(this, idx)}
                      isSelected={is_selected}
                      />;
              }.bind(this));
              return (
                  <ul style={ulStyle}>
                      {items}
                  </ul>
              );
          }
      });
      

      父级维护状态变量,该变量存储哪个 ListItem 是当前选定的。它在 render() 中使用此状态将 is_selected = true 传递给仅一个 ListItem,而将所有其他传递为 false。父级的状态由 clickHandler 更新,它作为 props 传递给每个 ListItem。见example fiddle here

      【讨论】:

        猜你喜欢
        • 2021-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多