我需要做类似这样的事情。 6个输入字段的类型编号。
每个标签都有min
和max
。问题是,如果我将红色设置为0-50,那么黄色不能从49-70开始,它需要根据周围的数字自动增加或减少,因此它总是一个接一个地变化吗?我正在使用React。
是否有一些用于此的小部件或连接多个数字输入的方法?
答案 0 :(得分:2)
如果要支持键盘输入,则必须在onBlur
处理程序中更新数字输入的范围,并更改onChange
中的输入值。这是一个带有自定义InputNumber
组件的示例,该组件隐藏了此onBlur / onChange详细信息:
class InputNumber extends React.Component {
state = {
value: this.props.value
}
onChange = e => {
this.setState({ value: +e.target.value });
};
onBlur = e => {
this.props.onChange(this.state.value);
};
componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.state.value) {
this.setState({ value: nextProps.value });
}
}
render() {
return <input
type='number'
{...this.props}
value={this.state.value}
onChange={this.onChange}
onBlur={this.onBlur}
/>;
}
}
class Demo extends React.Component {
state = {
ranges: [[1, 50], [51, 70], [71, 100]]
};
render() {
const { rangeRed, rangeYellow, rangeGreen } = this.state;
const controls = [
this.range('Red Scoring Range', 'red', 0),
this.range('Yellow Scoring Range', 'yellow', 1),
this.range('Green Scoring Range', 'green', 2)
];
return <table className='controls'>{controls}</table>;
}
range(label, color, idx) {
const { ranges } = this.state;
return (
<tr className='control-row'>
<td className='label'>{label}</td>
<td><div className={color + ' bullet'}></div></td>
<td>
<InputNumber
value={ranges[idx][0]}
onChange={this.onChange(idx, true)}
min={ranges[idx-1 < 0 ? 0 : idx-1][0] + 2}
max={ranges[idx][1] - 1}
disabled={idx === 0} />
</td>
<td>to</td>
<td>
<InputNumber
value={ranges[idx][1]}
onChange={this.onChange(idx, false)}
min={ranges[idx][0] + 1}
max={ranges[(idx+1) % ranges.length][1]-2}
disabled={idx === ranges.length-1} />
</td>
</tr>
);
}
onChange = (idx, isMin) => v => {
const ranges = [...this.state.ranges];
const min = isMin ? ranges[idx-1 < 0 ? 0 : idx-1][0] + 2 : ranges[idx][0] + 1;
const max = isMin ? ranges[idx][1] - 1 : ranges[(idx+1) % ranges.length][1]-2;
v = Math.min(Math.max(min, v), max);
if (!isMin && idx < ranges.length-1) {
ranges[idx][1] = v;
ranges[idx+1][0] = v+1;
} else if (isMin && idx > 0) {
ranges[idx][0] = v;
ranges[idx-1][1] = v-1;
}
this.setState({ ranges });
}
}
ReactDOM.render(<Demo />, document.getElementById('app'));
:root {
--bullet-size: 15px;
}
* {
color: #555;
}
.bullet {
display: inline-block;
height: var(--bullet-size);
width: var(--bullet-size);
border-radius: var(--bullet-size);
}
.red { background: red; }
.yellow { background: yellow; }
.green { background: green; }
td { padding: 5px; }
input {
width: 50px;
padding: 5px;
border: solid 1px #ccc;
border-radius: 3px;
}
<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"></div>
如果您希望即时更新范围,而又不关心键盘输入,则可以直接在onChange
处理程序中更新范围:
class Demo extends React.Component {
state = {
ranges: [0, 50, 70, 100]
};
render() {
const { rangeRed, rangeYellow, rangeGreen } = this.state;
const controls = [
this.range('Red Scoring Range', 'red', 0),
this.range('Yellow Scoring Range', 'yellow', 1),
this.range('Green Scoring Range', 'green', 2)
];
return <table className='controls'>{controls}</table>;
}
range(label, color, idx) {
const { ranges } = this.state;
return (
<tr className='control-row'>
<td className='label'>{label}</td>
<td><div className={color + ' bullet'}></div></td>
<td>
<input
type='number'
value={ranges[idx] + 1}
onChange={this.onChange(idx, true)}
max={ranges[idx+1] - 1}
disabled={idx === 0} />
</td>
<td>to</td>
<td>
<input
type='number'
value={ranges[idx+1]}
onChange={this.onChange(idx+1, false)}
min={ranges[idx] + 1}
disabled={idx+1 === ranges.length-1} />
</td>
</tr>
);
}
onChange = (idx, isMin) => e => {
const ranges = [...this.state.ranges];
const value = isMin ? +e.target.value - 1 : +e.target.value;
if (isMin && value > ranges[idx - 1] + 1 && value < ranges[idx + 1] + 1)
ranges[idx] = value;
if (!isMin && value < ranges[idx + 1] - 1 && value > ranges[idx - 1] + 1)
ranges[idx] = value;
this.setState({ ranges });
};
}
ReactDOM.render(<Demo />, document.getElementById('app'));
:root {
--bullet-size: 15px;
}
* {
color: #555;
}
.bullet {
display: inline-block;
height: var(--bullet-size);
width: var(--bullet-size);
border-radius: var(--bullet-size);
}
.red { background: red; }
.yellow { background: yellow; }
.green { background: green; }
td { padding: 5px; }
input {
width: 50px;
padding: 5px;
border: none;
border:solid 1px #ccc;
border-radius: 3px;
}
<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"></div>
答案 1 :(得分:0)
您可以在状态中动态设置输入的值,并触发事件以根据标记的更改来更改这些属性。
通过上一个或下一个输入值设置最小值和最大值之后
例如:
class YouClass extends React.Component {
constructor(props){
super(props)
this.state = {
redMaxValue: 50,
yellowMinValue: 51,
yellowMaxValue: 70,
greenMinValue: 71,
}
}
onChangeMaxRed = e =>{
this.setState({redMaxValue : e.target.value});
if(e.target.value >= this.state.yellowMinValue){
this.setState({yellowMinValue: e.target.value +1});
}
}
render(){
return(){
<div>
<input type="number" value="0" disabled />
<input type="number" value={this.state.redMaxValue} min="1" max={this.state.yellowMinValue} onChange={this.onChangeMaxRed} />
<input type="number" value={this.state.yellowMinValue} min={this.state.yellowMaxValue -1} max={yellowMaxValue -1} />
<input type="number" value={this.state.yellowMaxValue}" min={this.state.yellowMinValue + 1} max={redMinValue}/>
<input type="number" value={this.state.greenMinValue} min={this.state.yellowMaxValue} max={99} />
<input type="number" value="100" disabled />
</div>
}
}
}
我没有写所有的onChange函数,我想你明白了。
一个简单的版本没有最小和最大属性,而只有值。