【问题标题】:Creating a button that fills in React创建一个填充 React 的按钮
【发布时间】:2020-03-18 13:34:55
【问题描述】:

我是新来的,有一个问题我找不到答案..

我目前正在使用 ReactJS 开发一个网站,我希望有一个按钮,只要用户点击它,它就会自动填充。该按钮应该总共有 5 个阶段。

我并不是要您为我编写代码,而只是帮助我找到解决此问题的最佳方法。

我到底要问什么?正如你在这篇文章中看到的那样

这是一个装箱的元素,每当用户点击它(它可以点击整个元素),进度填充,它变成这样

所以第一行现在被标记了。当用户再次按下它时,第二条会填满

重要 - 这些条内会有填充的文本。

到目前为止我做了什么?我一直在考虑每次用户按下元素时有 5 个不同的图像,但我想知道是否有可能是一种更好的方法(比如让 DIV 作为图像的背景,并在用户按下时填充子 div...)

我希望我说清楚了,感谢大家抽出宝贵的时间!

【问题讨论】:

  • 看来你可以通过state管理它。不是吗?
  • 感谢您的快速回复!所以你说最好有 5 张图像并根据state 进行更改?如果是这样,它与我的想法相似。谢谢!
  • 谢谢,图片或 CSS 样式……都可以。

标签: javascript reactjs


【解决方案1】:

这是一个工作示例。您不需要所有不同状态的图像。使用 HTML 动态执行此操作要灵活得多。

这样做的关键是跟踪按钮被点击的次数。在这个例子中,它使用currentState 来跟踪它被点击了多少次。

const defaultStyle = {
  width: 100,
  padding: 5,
};

class MultiLevelButton extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = {
      currentState: 0,
    };
    
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleClick() {
    const { currentState } = this.state;
    
    if (currentState < this.props.states.length) {
      this.setState({
        currentState: currentState + 1,
      });
    }
  }
  
  reset() {
    this.setState({
      currentState: 0,
    });
  }
  
  render() {
    const { currentState } = this.state;
    const { states } = this.props;
    
    return (
      <button onClick={this.handleClick} style={{border: 'none', outline: 'none'}}>
        {
          states
            .map((s, i) => {
              const stateNumber = states.length - i;
              const overrides = stateNumber <= currentState ? { backgroundColor: '#000', color: '#fff' } : {};
              const style = {
                ...defaultStyle,
                backgroundColor: s,
                ...overrides,
              };
              return <div style={{...style}}>{stateNumber}</div>
            })
        }
      </button>
    )
  }
}

const buttonRef = React.createRef();

ReactDOM.render(
  <div>
    <MultiLevelButton ref={buttonRef} states={['#bbb', '#ccc', '#ddd', '#eee', '#fff']} />
    <MultiLevelButton states={['#fcc', '#cfc', '#ccf']} />
    <div>
      <button onClick={() => buttonRef.current.reset()}>Reset</button>
    </div>
  </div>,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="app" />

【讨论】:

  • 非常感谢!这比我的想法要好得多,它也教会了我很多!谢谢!
  • 关于您的解决方案的另一个小问题,有没有一种方法可以让这个按钮组件有一个函数“onClick”来检查某些条件,并且只有当它为真时,它才会改变按钮?
  • 是的,handleClick 函数已经这样做了:if (currentState &lt; this.props.states.length)。您可以在此处添加您喜欢的任何其他条件。
  • 再次感谢您,最后一个问题(希望如此),您建议我如何处理“重置”功能?就像有一个可以重置按钮级别状态的按钮。再次感谢您的大力帮助!
  • 您可以为此使用ref。我已经更新了答案以包含一个示例。见:reactjs.org/docs/refs-and-the-dom.html
【解决方案2】:

当您使用反应时。使用创建步骤/级别作为组件,您将传递样式的道具。您可以根据需要将该组件映射 5 次或 n 次。您显示的视图不需要图像使用 css 来实现它。

当用户点击它时改变组件的属性。

【讨论】:

    【解决方案3】:

    您可以使用状态来保持点击次数并根据点击次数更改按钮背景。

    const colors = ["#dfddc7", "#f58b54", "#a34a28", "#211717"]; //color array
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          index : 0
        }
      }
      handleChange() { // function will be called whenever we click on button
       let {index} = this.state;
       if (index >= 5) {
        return; // you don't want to change color after count 5
       }
       index++;
       console.log(index);
       this.setState({index})
      }
      render() {
       const {index} = this.state;
       return (
        <div className="App">
         <button style = {{background:colors[index]}} //we are setting dynamic color from array on the basis of index
           onClick = {this.handleChange.bind(this)}> click to change images 
         </button>
         </div>
       );
      }
    }
    

    【讨论】:

      【解决方案4】:

      您可以将&lt;div&gt;&lt;/div&gt; 放置在具有不同背景颜色而不是图像的按钮内。

      在下面的例子中,我保存了状态中的点击次数。通过将该值与step的index进行比较,可以看出是需要绿色还是透明

      const numberOfSteps = 5;
      class App extends React.Component {
        state = {
          numberOfClicks: 0
        };
      
        handleClick = e => {
          this.setState({
            numberOfClicks: (this.state.numberOfClicks + 1) % (numberOfSteps + 1)
          }); // Use module (%) to reset the counter after 5 clicks
        };
      
        render() {
          const { numberOfClicks } = this.state;
          const steps = Array(numberOfSteps)
            .fill()
            .map((v, i) => i)
            .map((i, index) => {
              const color = numberOfClicks >= index + 1 ? "limegreen" : "transparent";
              return (
                <div
                  style={{
                    backgroundColor: color,
                    height: "30px",
                    border: ".5px solid gray"
                  }}
                >
                  Bar {index + 1}
                </div>
              );
            });
          return (
            <button
              className="button"
              style={{ height: "200px", width: "200px", backgroundColor: "lightgreen" }}
              onClick={this.handleClick}
            >
              {steps}
            </button>
          );
        }
      }
      
      ReactDOM.render(<App />, document.getElementById("root"));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
      <div id="root">
        <!-- This element's contents will be replaced with your component. -->
      </div>

      【讨论】:

        【解决方案5】:

        关键概念是状态。当你点击你的按钮时,你应该设置一些状态,当你渲染按钮时,你应该根据状态来渲染它。

        这是一个简单的例子,我渲染了一个 button,它包含 5 个基于状态填充的 div 元素(通过设置 backgroundColor 样式属性)。

        class Example extends Component {
        
            constructor(props) {
                super(props);
        
                this.state = {
                    buttonState: 0,
                };
            }
        
            onClick = () => {
                let buttonState = this.state.buttonState;
                buttonState++;
                if(buttonState > 4) buttonState = 0; // wrap around from 4 - 0
                this.setState({buttonState: buttonState});
            }
        
            // render a button element with some text, and a background color based on whether filled is true/false
            renderButtonElement(elementText, filled) {
                const backgroundStyle = filled ? {backgroundColor: 'green'} : {backgroundColor: 'white'};
                const textStyle = {color: 'grey'};
        
                return(
                    <div style={[backgroundStyle, textStyle]}>
                        <div>{elementText}</div>
                    </div>
                );
            }
        
            render() {
                return(
                    <button
                        onClick={this.onClick}
                    >
                        {/*  make a temporary array of 5 elements, map over them and render an element for each one */}
                        {Array(5).fill().map((_, i) => this.renderButtonElement(i + 1, i <= this.state.buttonState))}
                    </button>
                );
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-30
          • 2019-02-06
          • 1970-01-01
          • 2022-01-12
          • 2018-10-15
          • 1970-01-01
          相关资源
          最近更新 更多