未调用输入onChange()事件

时间:2017-10-03 20:55:32

标签: javascript reactjs semantic-ui

  • 我正在渲染Input type='number'

  • 输入的值为this.state.value

  • 输入和所有UI组件都是通过 Semantic-UI 生成的,但我认为这不是重要的信息。

  • 此输入还有一个自定义箭头菜单,而不是原始输入。 [输入类型编号有两个箭头来减少/增加值]

渲染()

render() {
    // Custom Menu
    const arrowsMenu = (
    <Menu compact size='tiny'>
      <Menu.Item as='a' onClick={ this.decreaseNumber.bind(this) }>
        <Icon name='chevron left' size='small' />
      </Menu.Item>
      <Menu.Item as='a' onClick={ this.increaseNumber.bind(this) }>
        <Icon name='chevron right' size='small' />
      </Menu.Item>
    </Menu>
    );

    return (
      <Input value={ this.state.value } type="number" label={ arrowsMenu } placeholder="Raplece ma" onChange={ this.onChange.bind(this) } />
      );
  }

自定义菜单使用以下两个功能:

decreaseNumber(e) {
    this.setState({
      value: this.state.value - 1
    });
  }

  increaseNumber(e) {
    this.setState({
      value: this.state.value + 1
    });
  }

的onChange

你可以放置任何东西。

onChange(e) {
    console.log('====================================');
    console.log('Hello pals');
    console.log('====================================');
  }

问题是

每当我<{>>从Menu <推出箭头时,onChange()的{​​{1}}事件未被触发。但输入 已更改

(当然,因为状态中的Input变量已更改)

如果我对原始箭头执行相同操作,当然,值会按原样更改。

为什么会这样,我该如何解决?

2 个答案:

答案 0 :(得分:1)

仅当用户进入Input组件并与其交互以更改值(例如,如果他们键入新值)时,才会调用

onChange。如果您通过其他途径以编程方式更改值(在您的示例中通过自定义菜单更改它),则不会调用onChange

这是按照预期的设计工作。

如果您想触发onChange,请使用increaseNumberdecreaseNumber方法调用它。

答案 1 :(得分:0)

您可以使用您想要的任何代码调用onChange,但如果您想要反映新值,则需要根据事件中的新输入值设置状态。
对于decreaseNumberincreaseNumber,您还需要更改状态,但是您在这里进行计算,因此您需要确保它是一个数字(或将其转换为数字),因为您是从事件中获取一个字符串。

工作示例:

&#13;
&#13;
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 0
    };
  }

  onChange = e => this.setState({value: e.target.value});
  increaseNumber = () => this.setState({value: Number(this.state.value) + 1});
  decreaseNumber = () => this.setState({ value: Number(this.state.value) - 1 });

  render() {
    const { value } = this.state;
    return (
      <div>
        <button onClick={this.decreaseNumber}>-</button>
        <input type="number" value={value} onChange={this.onChange}/>
        <button onClick={this.increaseNumber}>+</button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
&#13;
<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="root"></div>
&#13;
&#13;
&#13;

修改 要触发onChange处理程序,只需调用this.onChange,但请注意,您无法像本机事件处理程序那样传递事件,但您可以传递一个模仿正常event的简单对象对象target.value
另一种选择是尝试通过ref触发它,但请记住,在某些情况下它会导致无限循环。 编辑示例:

&#13;
&#13;
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 0
    };
  }

  onChange = (e) => {
    this.setState({ value: e.target.value });
    console.log('change', e.target.value);
  }
  increaseNumber = () => {
    const { value } = this.state;
    const nextValue = Number(value) + 1;
    const changeEvent = {
      target: {
        value: nextValue
      }
    };
    this.onChange(changeEvent);
  }

  decreaseNumber = () => {
    const { value } = this.state;
    const nextValue = Number(value) - 1;
     const changeEvent = {
      target: {
        value: nextValue
      }
    };
    this.onChange(changeEvent);
  }

  render() {
    const { value } = this.state;
    return (
      <div>
        <button onClick={this.decreaseNumber}>-</button>
        <input type="number" value={value} onChange={this.onChange} />
        <button onClick={this.increaseNumber}>+</button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
&#13;
<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="root"></div>
&#13;
&#13;
&#13;

编辑#2
作为评论的后续内容:

  

列表的值是其内容/子项。如果有些孩子改变了,   然后列出他们的变化

嗯,这有一个简单的解决方案,您可以使用ref(就像我在答案的第一部分中提到的那样)并使用bubbles:true发送一个事件,这样它就会一直冒出来给父母 使用新的示例代码:

&#13;
&#13;
class App extends React.Component {
	liOnChange(e) {
		console.log('listed item/items changed');
	}
  
  inputOnChange(e) {
  	console.log('input changed');
  }
  handleClick(e){
    var event = new Event("input", { bubbles: true });
    this.myInput.dispatchEvent(event);
  }
	render() {
  	return(
			<div>
      	<ul>
        	<li onChange={this.liOnChange.bind(this)}>
        	  <input ref={ref => this.myInput = ref} type='text'onChange={this.inputOnChange.bind(this)}/>
            <button onClick={this.handleClick.bind(this)}>+</button>
        	</li>
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
&#13;
<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="root"></div>
&#13;
&#13;
&#13;

我一般不喜欢使用refs,但有时你需要它们。