เหตุการณ์ onKeyDown ไม่ทำงานบน div ใน React


92

ฉันต้องการใช้เหตุการณ์ keyDown กับ div ใน React ฉันทำ:

  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>
    )
  }

มันใช้งานได้ดี แต่ฉันต้องการทำในรูปแบบ React มากกว่านี้ ฉันเหนื่อย

        onKeyDown={this.onKeyPressed}

บนส่วนประกอบ แต่มันไม่ตอบสนอง มันใช้งานได้กับองค์ประกอบอินพุตเมื่อฉันจำได้

Codepen

ฉันจะทำมันได้อย่างไร?


โดยส่วนตัวแล้วฉันชอบแนวทางของคุณ นี่ดูเหมือนเป็นวิธีที่ดีในการผูกจังหวะสำคัญกับเอกสารซึ่งอยู่นอกขอบเขตของส่วนประกอบของคุณ และไม่ต้องการโฟกัสที่องค์ประกอบใดองค์ประกอบหนึ่ง
Daniel

คำตอบ:


159

คุณควรใช้แอตทริบิวต์tabIndexเพื่อให้สามารถฟังonKeyDownเหตุการณ์บน div ใน React การตั้งค่าtabIndex="0"ควรเริ่มการทำงานของตัวจัดการของคุณ


2
ดูเหมือนว่าจะเป็นการออกแบบที่ไม่ดีและมีความคิดเห็น จะเกิดอะไรขึ้นถ้าฉันต้องการจัดการกับเหตุการณ์ที่ทำให้เกิดฟองในองค์ประกอบคอนเทนเนอร์ แต่ไม่ควรให้ความสำคัญกับคอนเทนเนอร์นั้น
จะพี

1
ดูเหมือนว่าจะเป็นการแฮ็กหรือวิธีแก้ปัญหาสำหรับฉันมากกว่า อาจมีบางครั้งที่คุณต้องให้ div ที่กำหนดรักษาลำดับแท็บ
Iwnnay

11
tabIndex={-1}ยังสามารถใช้ได้หากคุณกำลังทำงานกับองค์ประกอบที่ไม่โต้ตอบและไม่ต้องการเปลี่ยนลำดับแท็บของเอกสาร
IliasT

1
คุณต้องตั้งค่า tabIndex เพื่อให้ div สามารถโฟกัสได้ คุณสามารถตั้งค่า tabIndex เป็น 0,1, -1 .... แต่ก่อนที่คุณจะทำเช่นนั้นให้ลองดูที่ webaim.org/techniques/keyboard/tabindex คุณอาจต้องการตั้งค่าเป็น -1 เนื่องจากคุณจัดการโดยใช้โปรแกรม .
วิตา

ด้วยเหตุผลบางประการสิ่งนี้ใช้ได้เฉพาะเมื่อฉันมีองค์ประกอบ <input> ใน div พร้อมกับ tabIndex หรืออย่างอื่นที่สามารถโฟกัสได้ ด้วย Div อื่น ๆ มันก็ยังไม่จับ ความคิดใด ๆ ?
Flion

24

คุณต้องเขียนด้วยวิธีนี้

<div 
    className="player"
    style={{ position: "absolute" }}
    onKeyDown={this.onKeyPressed}
    tabIndex="0"
  >

ถ้าonKeyPressedไม่ได้ผูกไว้กับแล้วพยายามที่จะเขียนมันโดยใช้ฟังก์ชั่นลูกศรหรือผูกไว้ในส่วนประกอบthisconstructor


2
ขออภัย. ฉันแน่ใจว่าฉันมองข้ามเรื่องนี้ไป แต่นี่ไม่ใช่ปัญหา มันยังใช้ไม่ได้
Michael

คำตอบที่อัปเดต คุณควรคลิกที่ div หรือนำไปโฟกัสก่อนที่จะกดปุ่มใด ๆ
เสือดำ

ฉันทำ. มันไม่ทำงาน ฉันอัปเดตโค้ดด้านบนแล้ว ทำงานได้ดีกับคำสั่ง DOM แต่ไม่ใช่ในรูปแบบ React
Michael

คุณช่วยอธิบายได้ไหมว่าอะไรใช้ไม่ได้? ฟังก์ชันของคุณไม่ได้รับการเรียกหรือconsole.logไม่มีการแสดงผลอะไร
Panther

ไม่ได้เรียกใช้ฟังก์ชันนี้ ฉันมี codepen A: codepen.io/lafisrap/pen/OmyBYG ประมาณบรรทัด 275 และ 307
Michael

7

คุณคิดมากเกินไปใน Javascript แท้ กำจัดผู้ฟังของคุณด้วยวิธี React lifecycle และใช้event.keyแทนevent.keyCode(เนื่องจากนี่ไม่ใช่ออบเจ็กต์เหตุการณ์ JS แต่เป็น React SyntheticEvent ) ส่วนประกอบทั้งหมดของคุณอาจทำได้ง่าย ๆ เช่นนี้ (สมมติว่าคุณไม่ได้ผูกวิธีการของคุณไว้ในตัวสร้าง)

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>
  )
}

นั่นคือสิ่งที่ฉันต้องการเขียน แต่นรกมันไม่ไป นี่คือ codepen นี้: codepen.io/lafisrap/pen/OmyBYG หากคุณแสดงความคิดเห็นในบรรทัด 275 แสดงว่าอินพุตคียบอร์ด (ปุ่มเคอร์เซอร์) ไม่ทำงาน onKeyDown อยู่ในบรรทัดที่ 307
Michael

keyCode ฉันใช้สำหรับปุ่มเคอร์เซอร์เนื่องจากไม่ส่งคืนอักขระ
Michael

1
React ไม่ใช้วัตถุเหตุการณ์ Javascript ดังนั้นจึงไม่มีคุณสมบัติ keyCode ว่าeventวัตถุเป็น React SyntheticEvent
เหล็ก

@ ไมเคิลฉันยังไม่แน่ใจว่าคุณจะเรียกเหตุการณ์สำคัญบน div อย่างไร แต่เมื่อฉันใส่รหัสนี้ลงในซอด้วยonClickเสาแทนที่จะonKeyDownเป็นตัวจัดการจะยิง
เหล็ก

ขอบคุณ. นั่นอธิบายว่า ... เหตุการณ์สำคัญทำงานในช่องป้อนข้อมูล
Michael

2

คำตอบด้วย

<div 
    className="player"
    onKeyDown={this.onKeyPressed}
    tabIndex={0}
>

ได้ผลสำหรับฉันโปรดทราบว่า tabIndex ต้องการตัวเลขไม่ใช่สตริงดังนั้น tabIndex = "0" จึงไม่ทำงาน


อาจแก้ไขคำตอบอื่นหรือไม่
Ross Attrill

1

การใช้divเคล็ดลับกับtab_index="0"หรือใช้tabIndex="-1"งานได้ แต่เมื่อใดก็ตามที่ผู้ใช้โฟกัสมุมมองที่ไม่ใช่องค์ประกอบคุณจะได้รับโครงร่างโฟกัสที่น่าเกลียดบนเว็บไซต์ทั้งหมด ซึ่งสามารถแก้ไขได้โดยตั้งค่า CSS สำหรับ div เพื่อใช้outline: noneในโฟกัส

นี่คือการใช้งานกับส่วนประกอบที่มีสไตล์:

import styled from "styled-components"

const KeyReceiver = styled.div`
  &:focus {
    outline: none;
  }
`

และในคลาส App:

  render() {
    return (      
      <KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}>
          Display stuff...
      </KeyReceiver>
    )

-1

คุณไม่มีการเชื่อมโยงของวิธีการในตัวสร้าง นี่คือวิธีที่ React แนะนำให้คุณทำ:

class Whatever {
  constructor() {
    super();
    this.onKeyPressed = this.onKeyPressed.bind(this);
  }

  onKeyPressed(e) {
    // your code ...
  }

  render() {
    return (<div onKeyDown={this.onKeyPressed} />);
  }
}

มีวิธีอื่นในการทำเช่นนี้ แต่จะมีประสิทธิภาพสูงสุดในขณะรันไทม์


-3

คุณต้องป้องกันไม่ให้เหตุการณ์เริ่มต้นทริกเกอร์

onKeyPressed(e) {
   e.preventDefault();
   console.log(e.key);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.