JSX React HTML5输入滑块不起作用

时间:2016-03-21 02:02:50

标签: javascript reactjs slider react-jsx

我正在使用React.JS进行构建,并且正在构建一个范围输入滑块,其中包含两个组件选项。

这是我的代码:

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

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

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

谢谢!

5 个答案:

答案 0 :(得分:32)

用户互动无效,因为<input>道具value被视为受控。这意味着显示的值完全由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"/>
  );
}

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

有关官方documentation

的详情

答案 1 :(得分:3)

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

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

简单地说,这有效:

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

现在,您可能需要其输出来执行某些操作。您可以在答案中使用onChange={this.handleChange}作为@xCrZx状态。但在handleChange内,你不一定要更新你的州。根据您的逻辑,您可以避免增加状态的复杂性,只需在handleChange内编写逻辑代码。

如果你避免更新状态,你可能会保存一些渲染,你的表现会有所改善。

答案 2 :(得分:1)

试试这个:

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

我建议改变价值=&#34; 3&#34;到 defaultValue =&#34; 3&#34; ,否则我认为价值被硬编码为&#34; 3&#34;可能很难或不可能改变。 onInput函数查找该值并将其添加到state,以便将数据传递给另一个组件或函数。对您的问题可能有一个更优雅的解决方案,但上述方法应该有效。

答案 3 :(得分:1)

我希望以上解决方案可以解决您的问题,我有一种使用钩子的简单方法。

const RangeSlider = () => {

  const [rangeval, setRangeval] = useState(null);

  return (
    <div>
      <input type="range" className="custom-range" min="199" max="3999" 
       onChange={(event) => setRangeval(event.target.value)} />
      <h4>The range value is {rangeval}</h4>
    </div>
  );
};

export default RangeSlider;

答案 4 :(得分:0)

这是一个解决方案,用于制作多个滑块的形式,甚至是传递了事件处理程序的单个滑块 我们可以简单地使用Range类型的HTML输入 rc-sliderreact-input-range未发送事件处理程序 onChangeonAfterChange他们隐式发送了滑块的值,因此我们不能处理滑块的形式或动态创建它们。

jsfiddle snippet

有关详情,我们可以查看HTML input Range

提供的CSS-Tricks和CSS

&#13;
&#13;
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"));
&#13;
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;
  }
&#13;
<!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>
&#13;
&#13;
&#13;

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

使用CodeSandbox