Chcę użyć zdarzenia keyDown na div w Reakcie. Ja robię:
componentWillMount() {
document.addEventListener("keydown", this.onKeyPressed.bind(this));
}
componentWillUnmount() {
document.removeEventListener("keydown", this.onKeyPressed.bind(this));
}
onKeyPressed(e) {
console.log(e.keyCode);
}
render() {
let player = this.props.boards.dungeons[this.props.boards.currentBoard].player;
return (
<div
className="player"
style={{ position: "absolute" }}
onKeyDown={this.onKeyPressed} // not working
>
<div className="light-circle">
<div className="image-wrapper">
<img src={IMG_URL+player.img} />
</div>
</div>
</div>
)
}
Działa dobrze, ale chciałbym to zrobić bardziej w stylu React. próbowałem
onKeyDown={this.onKeyPressed}
na komponencie. Ale to nie reaguje. O ile pamiętam, działa na elementach wejściowych.
Jak mogę to zrobić?
Odpowiedzi:
Powinieneś użyć atrybutu tabIndex, aby móc nasłuchiwać
onKeyDown
zdarzenia elementu div w Reakcie. UstawienietabIndex="0"
powinno zwolnić program obsługi.źródło
tabIndex={-1}
może być również używany, jeśli pracujesz z elementem, który nie jest interaktywny i nie chcesz zmieniać kolejności tabulacji w dokumencie.Musisz to napisać w ten sposób
<div className="player" style={{ position: "absolute" }} onKeyDown={this.onKeyPressed} tabIndex="0" >
Jeśli
onKeyPressed
nie jest powiązanythis
, spróbuj przepisać go za pomocą funkcji strzałek lub powiązać w komponencieconstructor
.źródło
console.log
nic nie wyświetla?Za dużo myślisz w czystym JavaScript. Pozbądź się słuchaczy na tych metodach cyklu życia React i używaj
event.key
zamiast nichevent.keyCode
(ponieważ nie jest to obiekt zdarzenia JS, jest to React SyntheticEvent ). Twój cały komponent może być tak prosty (zakładając, że nie ograniczyłeś swoich metod w konstruktorze).onKeyPressed(e) { console.log(e.key); } render() { let player = this.props.boards.dungeons[this.props.boards.currentBoard].player; return ( <div className="player" style={{ position: "absolute" }} onKeyDown={this.onKeyPressed} > <div className="light-circle"> <div className="image-wrapper"> <img src={IMG_URL+player.img} /> </div> </div> </div> ) }
źródło
event
obiekt to React SyntheticEvent .onClick
rekwizytem, zamiast programuonKeyDown
obsługi odpala.Odpowiedź z
<div className="player" onKeyDown={this.onKeyPressed} tabIndex={0} >
działa dla mnie, pamiętaj, że tabIndex wymaga liczby, a nie ciągu, więc tabIndex = "0" nie działa.
źródło
Korzystanie z tej
div
sztuczki ztab_index="0"
lubtabIndex="-1"
działa, ale za każdym razem, gdy użytkownik skupia się na widoku, który nie jest elementem, otrzymasz brzydki zarys całej witryny. Można to naprawić, ustawiając CSS dla elementu div, który ma być używanyoutline: none
w fokusie.Oto implementacja ze stylizowanymi komponentami:
import styled from "styled-components" const KeyReceiver = styled.div` &:focus { outline: none; } `
aw klasie App:
render() { return ( <KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}> Display stuff... </KeyReceiver> )
źródło
Brakuje powiązania metody w konstruktorze. Tak sugeruje React:
class Whatever { constructor() { super(); this.onKeyPressed = this.onKeyPressed.bind(this); } onKeyPressed(e) { // your code ... } render() { return (<div onKeyDown={this.onKeyPressed} />); } }
Są na to inne sposoby, ale będzie to najbardziej wydajne w czasie wykonywania.
źródło
Musisz uniemożliwić wywołanie domyślnego zdarzenia.
onKeyPressed(e) { e.preventDefault(); console.log(e.key); }
źródło