JSX React HTML5 输入滑块不工作
JSX React HTML5 Input Slider Doesn't Work
我正在使用 React.JS 进行构建,并且正在构建一个具有两个组件选择的范围输入滑块。
这是我的代码:
<input id="typeinp" type="range" min="0" max="5" value="3" step="1"/>
当我将它放入我的客户端渲染组件并尝试切换它时,它根本没有移动。在我正在进行的 JS/PHP 构建中对其进行测试,它工作正常。
为什么这在 JSX/React.JS 中不起作用?建议的解决方法是什么?
谢谢!
试试这个:
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",否则我认为该值被硬编码为“3”,可能很难或无法更改。 onInput 函数找到该值并将其添加到状态,以便可以将数据传递给另一个组件或函数。您的问题可能有更优雅的解决方案,但上面的方法应该有效。
用户交互没有影响,因为带有 value
道具的 <input>
被视为 受控 。这意味着显示值完全由 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
我认为之前的答案可以解决您的问题。但是,我会说解决方案不需要涉及 React 状态。
冻结输入滑块的唯一原因是您已将其值硬编码为 3,正如@Colin Whitmarsh 所建议的那样。
简单地说,这有效:
<input id="typeinp" type="range" min="0" max="5" defaultValue="3" step="1"/>
现在,您可能需要它的输出来做一些事情。您可以使用 onChange={this.handleChange}
作为@xCrZx 在他的回答中指出的那样。但是在 handleChange
里面你不一定要更新你的状态。根据您的逻辑,您可以避免增加状态的复杂性,只需在 handleChange
.
中编写您的逻辑即可
如果你避免更新状态,你可能会保存一些渲染并且你的性能会提高。
这里有一个解决方案,用于制作多个滑块甚至一个带有事件处理程序的滑块
我们可以简单地使用 Range 类型的 HTML 输入
rc-slider and react-input-range 不发送 事件处理程序 onChange
或 onAfterChange
它们隐式发送滑块的值,因此我们无法处理滑块的形式或创建他们在飞行中。
更多信息我们可以查看HTML input Range and CSS provided by CSS-Tricks
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>
这个解决方案非常适合我 ;)
我希望以上解决方案可能已经解决了您的问题,我有一种使用挂钩的简单方法。
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;
我正在使用 React.JS 进行构建,并且正在构建一个具有两个组件选择的范围输入滑块。
这是我的代码:
<input id="typeinp" type="range" min="0" max="5" value="3" step="1"/>
当我将它放入我的客户端渲染组件并尝试切换它时,它根本没有移动。在我正在进行的 JS/PHP 构建中对其进行测试,它工作正常。
为什么这在 JSX/React.JS 中不起作用?建议的解决方法是什么?
谢谢!
试试这个:
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",否则我认为该值被硬编码为“3”,可能很难或无法更改。 onInput 函数找到该值并将其添加到状态,以便可以将数据传递给另一个组件或函数。您的问题可能有更优雅的解决方案,但上面的方法应该有效。
用户交互没有影响,因为带有 value
道具的 <input>
被视为 受控 。这意味着显示值完全由 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
我认为之前的答案可以解决您的问题。但是,我会说解决方案不需要涉及 React 状态。
冻结输入滑块的唯一原因是您已将其值硬编码为 3,正如@Colin Whitmarsh 所建议的那样。
简单地说,这有效:
<input id="typeinp" type="range" min="0" max="5" defaultValue="3" step="1"/>
现在,您可能需要它的输出来做一些事情。您可以使用 onChange={this.handleChange}
作为@xCrZx 在他的回答中指出的那样。但是在 handleChange
里面你不一定要更新你的状态。根据您的逻辑,您可以避免增加状态的复杂性,只需在 handleChange
.
如果你避免更新状态,你可能会保存一些渲染并且你的性能会提高。
这里有一个解决方案,用于制作多个滑块甚至一个带有事件处理程序的滑块
我们可以简单地使用 Range 类型的 HTML 输入
rc-slider and react-input-range 不发送 事件处理程序 onChange
或 onAfterChange
它们隐式发送滑块的值,因此我们无法处理滑块的形式或创建他们在飞行中。
更多信息我们可以查看HTML input Range and CSS provided by CSS-Tricks
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>
这个解决方案非常适合我 ;)
我希望以上解决方案可能已经解决了您的问题,我有一种使用挂钩的简单方法。
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;