为keydown添加事件监听器以响应元素

时间:2017-12-21 21:49:10

标签: javascript reactjs

我试图在图片(或div)标记中为keydown事件添加事件监听器。如果我用document.addEventListener将它添加到文档中,它就可以工作,但是当我尝试将它放入我在反应中创建的特定元素时它没有用(我在代码中注意到什么有效,什么没有&# 39; T)。 handleClick也有效,handleKey无效,无论我将哪种格式添加到标记中。

class PrescriptionImage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      patient: "",
      rotation: 0
    };
    this.handleKey = this.handleKey.bind(this);
  }

  handleClick() {
    this.setState({rotation: this.state.rotation + 270})
  }

  handleKey(e) {
    e.preventDefault();
    console.log(e);
    if (e.code == 'ArrowLeft') {
      if (e.ctrlKey) {
        this.setState({rotation: this.state.rotation + 270})
      }
    }
  }

  componentDidMount() {
//    document.getElementById("left").addEventListener("keydown", this.handleKey, true); This doesn't work (no error)
//    this.RxImage.addEventListener("keydown", this.handleKey, false); This doesn't work, (can't find addEventListener of "undefined")
//    document.addEventListener("keydown", this.handleKey, false); This works.
    fetch("http://localhost:3333/patientAddress.json")
      .then(res => res.json())
      .then(
        result => {
          this.setState({
            isLoaded: true,
            patient: result.order.patient
          });
        },
        error => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      );
  }

  componentWillUnmount(){
    document.removeEventListener("keydown", this.handleKey, false);
  }

  render() {
    const { error, isLoaded, patient, rotation } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return <img className="prescription-image" style={{width: "98%", height: "98%", transform: `rotate(${rotation}deg)`}} src={"data:image/png;base64," + patient.rx.imageData} onClick={() => this.handleClick()} onKeyDown={this.handleKey} />;
    }
  }
}

ReactDOM.render(<PrescriptionImage />, document.getElementById("left"));

2 个答案:

答案 0 :(得分:2)

这里有两个主要问题:

  1. keyDown事件需要div成为焦点。一种方法 是向tabindex添加div属性。在你专注于它之后 您可以在键盘上的任何键上触发onKeyDown事件。
  2. 在您的处理程序中,您正在尝试检查e.code,但实际上是。{ 正确的属性是e.keycode 话虽如此,你应该仔细read about the browsers support for it,因为它被认为在某些浏览器中被弃用了 Here is a list of the available properties of this event and their status(例如,查看key)。
  3. 修改
    我使用ref API of react添加了另一种方法。 这样,您就可以像以前那样附加事件监听器,并通过代码触发焦点(参见componentDidMount)。

    这是一个正在运行的例子:

    class App extends React.Component {
    
      componentDidMount() {
        this.myDiv.addEventListener('keydown', this.handleKey);
        this.myDiv.focus();
      }
    
      componentWillUnmount() {
        this.myDiv.removeEventListener('keydown', this.handleKey);
      }
    
      handleKey = e => {
        console.log(e.keyCode);
      }
    
      render() {
        return (
          <div>
            <div tabIndex="0" onKeyDown={this.handleKey}>click me</div>
            <div tabIndex="1" ref={ref => this.myDiv = ref}>by ref</div>
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <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>

答案 1 :(得分:0)

此实施对我来说效果很好。

class App extends React.Component {

  constructor(props) {
    super(props);
    this.myDiv = React.createRef();
  }

  componentDidMount() {
    this.myDiv.current.addEventListener('keydown', this.handleKey);
    this.myDiv.current.focus();
  }

  componentWillUnmount() {
    this.myDiv.current.removeEventListener('keydown', this.handleKey);
  }

  handleKey = e => {
    console.log(e.keyCode);
  }

  render() {
    return (
      <div>
        <div tabIndex="0" onKeyDown={this.handleKey}>click me</div>
        <div tabIndex="1" ref={this.myDiv}>by ref</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));