Javascript JSX React HTML5 输入滑块不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36122034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:39:57  来源:igfitidea点击:

JSX React HTML5 Input Slider Doesn't Work

javascriptreactjssliderreact-jsx

提问by CodeFromthe510

I'm using React.JS for a build, and am building a range input slider with two choices for a component.

我正在使用 React.JS 进行构建,并且正在构建一个具有两个组件选择的范围输入滑块。

this is my code:

这是我的代码:

<input id="typeinp" type="range" min="0" max="5" value="3" step="1"/>

When I place it into my client side rendering component and try to toggle it it does not move at all. Testing it onto a JS/PHP build I have going on, it works fine.

当我将它放入我的客户端渲染组件并尝试切换它时,它根本不会移动。在我正在进行的 JS/PHP 构建上测试它,它工作正常。

Why does this not work in JSX/React.JS and what would be a suggested work around?

为什么这在 JSX/React.JS 中不起作用,建议的解决方法是什么?

Thanks!

谢谢!

回答by xCrZx

User interactions have no effect because an <input>with valueprop is considered as controlled. It means that displayed value is controlled entirely by renderfunction. So to actually update input value you should use the onChangeevent. Example:

用户交互没有影响,因为<input>withvalue道具被认为是受控的。这意味着显示值完全由render功能控制。因此,要实际更新输入值,您应该使用该onChange事件。例子:

getInitialState: function() {
  return {value: 3};
},
handleChange: function(event) {
  this.setState({value: event.target.value});
},
render: function() {
  return (
    <input 
      id="typeinp" 
      type="range" 
      min="0" max="5" 
      value={this.state.value} 
      onChange={this.handleChange}
      step="1"/>
  );
}

You can also use defaultValueinstead of value. In this case <input>is considered as uncontrolledand any user interactions are immediately reflected by element itself without invoking renderfunction of your component.

您也可以使用defaultValue代替value。在这种情况下<input>被认为是不受控制的,任何用户交互都会立即由元素本身反映,而无需调用render组件的功能。

More on this in official documentation

更多关于这个的官方文档

回答by Daniel Reina

I think previous answers fix your problem. However, I'd say the solution doesn't need to involve React states.

我认为以前的答案可以解决您的问题。但是,我认为该解决方案不需要涉及 React 状态。

The only reason behind your frozen input slider is that you've hardcoded its value to 3, as @Colin Whitmarsh suggests.

正如@Colin Whitmarsh 所建议的那样,冻结输入滑块背后的唯一原因是您已将其值硬编码为 3。

Simply, this works:

简单地说,这有效:

<input id="typeinp" type="range" min="0" max="5" defaultValue="3" step="1"/>

Now, you probably need its output to do something. You can use onChange={this.handleChange}as @xCrZx states in his answer. But inside handleChangeyou don't necessarily have to update your state. Depending on your logic, you could avoid increasing the complexity of your state and simply code your logic inside handleChange.

现在,您可能需要它的输出来做某事。您可以onChange={this.handleChange}在他的回答中使用@xCrZx 状态。但在内部,handleChange您不一定必须更新您的状态。根据您的逻辑,您可以避免增加状态的复杂性,只需在handleChange.

If you avoid updating the state, you'll probably save some renders and your performance will improve.

如果你避免更新状态,你可能会保存一些渲染并且你的性能会提高。

回答by Colin Whitmarsh

Try this:

尝试这个:

onInput() {
    var input = document.getElementById("typeinp");
    var currentVal = input.value;
    this.setState({
      value: currentVal
    })
}

<input id="typeinp" type="range" min="0" max="5" step="1" defaultValue="3" onInput={this.onInput.bind(this)}/>

I suggest changing value="3" to defaultValue="3", otherwise I think value is hardcoded to "3" and may be difficult or impossible to change. The onInput function finds the value and adds it to state so the data can be passed to another component or function. There's likely a more elegant solution to your problem, but the above should work.

我建议将 value="3" 更改为defaultValue="3",否则我认为 value 被硬编码为 "3" 并且可能很难或不可能更改。onInput 函数找到该值并将其添加到状态,以便将数据传递给另一个组件或函数。您的问题可能有更优雅的解决方案,但上述方法应该可行。

回答by Abdallah Okasha

Here's a solution for making form of multiple sliders or even one single slider with event handler passed we can simply use HTML input of type Range rc-sliderand react-input-rangedon't sent event handleronChangeor onAfterChangethey sends the slider's value Implicitly, so we can't handle form of sliders or create them on the fly.

这是一种用于制作多个滑块甚至一个带有事件处理程序的滑块的解决方案,我们可以简单地使用 Range rc-slider类型的 HTML 输入, 而react-input-range不发送事件处理程序,onChange或者onAfterChange它们隐式地发送滑块的值,所以我们无法处理滑块的形式或动态创建它们。

jsfiddle snippet

jsfiddle 片段

For more we can check HTML input Rangeand CSS provided by CSS-Tricks

有关更多信息,我们可以查看CSS-Tricks提供的HTML 输入范围和 CSS

class SlidersExample extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      slidersLabels: ["A", "B", "C", "D"],
      sumOfCustomWeights: 0,
      slidersWeights: []
    };
  }
  componentDidMount() {
    const slidersLabels = this.state.slidersLabels;
    const slidersWeights = [];
    for (var i = 0; i < slidersLabels.length; ++i)
      slidersWeights[slidersLabels[i]] = 0;
    this.setState({ slidersWeights });
  }

  render() {
    return (
      <div>
        {this.generateSliders()}
        <span> Total Weights: {this.state.sumOfCustomWeights} </span>
      </div>
    );
  }
  generateSliders() {
    const slidersLabels = this.state.slidersLabels;
    var sliders = [];
    for (var i = 0; i < slidersLabels.length; ++i) {
      sliders.push(
        <div style={{ marginTop: "20px", marginBottom: "20px" }}>
          <span style={{ fontSize: "16px", marginBottom: "6px" }}>
            {" "}
            {slidersLabels[i]} ({this.state.slidersWeights[slidersLabels[i]]})%
          </span>
          <input
            id={slidersLabels[i]}
            type="range"
            defaultValue="0"
            min="0"
            max="100"
            className="slider"
            onChange={this.handleSliderChange.bind(this)}
            step="1"
          />
        </div>
      );
    }
     return sliders;
  }
  handleSliderChange(event) {
    //console.log(event.target.value, " ", event.target.id);
    var id = event.target.id;
    var value = event.target.value;
    const slidersWeights = this.state.slidersWeights;
    slidersWeights[id] = parseInt(value);
    var sumOfCustomWeights = 0;
    const slidersLabels = this.state.slidersLabels;
    for (var i = 0; i < slidersLabels.length; i++)
      sumOfCustomWeights += slidersWeights[slidersLabels[i]];
    this.setState({ slidersWeights, sumOfCustomWeights });
  }
}

ReactDOM.render(<SlidersExample />, document.querySelector("#app"));
input[type=range] {
  -webkit-appearance: none;
  margin: 18px 0;
  width: 100%;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
  width: 100%;
  height: 8.4px;
  cursor: pointer;
  animate: 0.2s;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  background: #3071a9;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -14px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}
input[type=range]::-moz-range-track {
  width: 100%;
  height: 8.4px;
  cursor: pointer;
  animate: 0.2s;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  background: #3071a9;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}
input[type=range]::-moz-range-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}
input[type=range]::-ms-track {
  width: 100%;
  height: 8.4px;
  cursor: pointer;
  animate: 0.2s;
  background: transparent;
  border-color: transparent;
  border-width: 16px 0;
  color: transparent;
}
input[type=range]::-ms-fill-lower {
  background: #2a6495;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
  background: #3071a9;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
  background: #3071a9;
}
input[type=range]:focus::-ms-fill-upper {
  background: #367ebd;
}

#app{
  margin-right: 100px;
  margin-left: 100px;
  margin-bottom: 100px;
  }
<!DOCTYPE html>
<html>
<body>


<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>
<div id="app"> </div>
</body>
</html>

This solution working perfectly with me ;)

这个解决方案与我完美配合;)

Using CodeSandbox

使用CodeSandbox