【问题标题】:JSX React HTML5 Input Slider Doesn't WorkJSX React HTML5 输入滑块不起作用
【发布时间】:2016-07-07 10:19:41
【问题描述】:

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

这是我的代码:

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

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

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

谢谢!

【问题讨论】:

  • 这个客户端渲染组件是什么样子的?

标签: javascript reactjs slider react-jsx


【解决方案1】:

用户交互无效,因为带有value 属性的&lt;input&gt; 被视为受控。这意味着显示的值完全由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。在这种情况下,&lt;input&gt; 被认为是不受控制的,并且任何用户交互都会立即由元素本身反映,而无需调用组件的 render 函数。

更多信息请关注官方documentation

【讨论】:

  • 感谢您提供信息丰富的回复。我最终使用了构造函数(ES6 语法)并使用了一个默认值来实现这一点。也感谢官方文档的链接。
  • [!] 使用 ES6 类时应在构造函数中初始化状态,使用 React.createClass 时应定义 getInitialState 方法。
【解决方案2】:

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

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

很简单,这行得通:

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

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

如果你避免更新状态,你可能会节省一些渲染,你的性能会提高。

【讨论】:

    【解决方案3】:

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

    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】:

      试试这个:

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

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

      【讨论】:

      • 谢谢! defaultvalue 和 state 函数起到了作用。虽然我最终确实创建了一个构造函数并为其分配了一个默认值
      【解决方案5】:

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

      jsfiddle snippet

      更多我们可以查看HTML input RangeCSS-Tricks提供的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>

      这个解决方案非常适合我 ;)

      使用CodeSandbox

      【讨论】:

        猜你喜欢
        • 2021-12-06
        • 1970-01-01
        • 2015-12-29
        • 2023-02-22
        • 2013-05-18
        • 1970-01-01
        • 1970-01-01
        • 2011-06-12
        相关资源
        最近更新 更多