2015-08-27 26 views
10

Tôi đang cố gắng thực hiện một số phát hiện nhấn phím rất cơ bản và tôi không thể làm cho nó hoạt động. Tôi có một thành phần trần rằng nên được chọn lên trên các sự kiện onKeyDown nhưng không bị đăng xuất khỏi trong giao diện điều khiển:Phản ứng không đáp ứng với sự kiện quan trọng

class App extends React.Component { 
    constructor(props) { 
    super(props); 
    } 

    handleKeyDown(event) { 
    console.log('handling a key press'); 
    } 

    render() { 
    return (
     <ChildComponent onKeyDown={this.handleKeyDown} /> 
    ); 
    } 
} 

React.render(<App />, document.getElementById('app')); 

Trả lời

4

Vấn đề là ChildComponent không phải là thành phần mà là nhà máy thành phần. Nó sẽ được thay thế bằng kết quả của việc hiển thị phần tử được tạo với nhà máy đó.

Chèn ChildComponent vào div và đính kèm bất kỳ trình xử lý sự kiện nào vào div, chứ không phải ChildComponent. Thay thế <div> bằng <span> nếu bạn cần hiển thị nội tuyến.

let {Component} = React; 

class ChildComponent extends Component { 
    render() { 
    return (<child-component>click me</child-component>); 
    } 
} 

class App extends Component { 
    handleClick(event) { 
    console.log('handling a key press'); 
    } 

    render() { 
    return (<div onClick={this.handleClick}><ChildComponent /></div>); 
    } 
} 

React.render(<App />, document.getElementById('app')); 

Nhìn thấy nó trong hành động trên codepen

+0

Tôi đã nhận thấy điều này cũng đang cố gắng áp dụng các kiểu. Thay vì áp dụng cho phần tử DOM cấp cao nhất bên trong thành phần, các kiểu chỉ được thả xuống sàn. –

28

Bạn sẽ cần phải gán một -attribute tabIndex cho các phần tử của bạn (các yếu tố gói ví dụ) để nó nhận được nhấn phím. Sau đó vượt qua handler keyDown để nó với các đạo cụ:

import React from 'react'; 
import { render } from 'react-dom'; 

class ChildComponent extends React.Component { 
    constructor(props) { 
    super(props); 
    } 
    render() { 
    return (
     <div tabIndex="0" onKeyDown={this.props.handleKeyDown}>Fooo</div> 
    ); 
    } 
} 

class App extends React.Component { 
    constructor(props) { 
    super(props); 
    } 

    handleKeyDown(event) { 
    console.log('handling a key press'); 
    } 

    render() { 
    return (
     <ChildComponent handleKeyDown={() => this.handleKeyDown()} /> 
    ); 
    } 
} 

render(<App />, document.getElementById('app')); 
+0

Bất kỳ lý do nào tại sao cần chỉ mục tab? – user1095118

+1

@ user1095118 đó là cách duy nhất các yếu tố bên cạnh các liên kết và các yếu tố biểu mẫu có thể nhận được tiêu điểm bàn phím và do đó nhấn phím. Nó được đặt thành 0 để nó không ghi đè thứ tự tab gốc. Xem http://webaim.org/techniques/keyboard/tabindex để biết thêm thông tin. –

0

Trong một ứng dụng đội của tôi đang làm việc trên, chúng tôi đang sử dụng react-hotkey. Thật không may, React dường như không hỗ trợ mixins với cú pháp ES6, nhưng nếu bạn đang mát mẻ với một số babel, bạn có thể cho nó một thử.

let App = React.createClass({ 
    mixins: [hotkey.Mixin('handleKeyDown')], 

    componentDidMount() { 
    hotkey.activate(); 
    }, 

    componentWillUnmount() { 
    hotkey.disable(); 
    }, 

    handleKeyDown(event) { 
    console.log('handling a key press'); 
    }, 

    render() { 
    return (
     <ChildComponent /> 
    ); 
    } 
}); 

React.render(<App />, document.getElementById('app')); 
6

DOM muốn nguyên tố này được tập trung để nhận sự kiện bàn phím. Nếu bạn không muốn hack phần tử với tabIndex hoặc contentEditable để tập trung vào, bạn có thể sử dụng trình nghe sự kiện DOM gốc trên window và xác định trình xử lý khác trong mỗi thành phần xử lý các sự kiện bàn phím.

Chỉ cần chắc chắn để loại bỏ các sự kiện người nghe khi mà unmounts phần vì vậy tất cả các thành phần không được xử lý tất cả các thời gian:

componentWillMount: function() { 
    window.addEventListener('keydown', this.handleKeyDown); 
    }, 

    componentWillUnmount: function() { 
    window.removeEventListener('keydown', this.handleKeyDown); 
    }, 

Ngoài ra, dường như có một NPM cung cấp chức năng tương tự nếu đó là dễ dàng hơn: https://www.npmjs.com/package/react-keydown

+0

Hãy nhớ ràng buộc trình xử lý sự kiện của bạn trong hàm tạo nếu bạn muốn 'this' là thành phần: ' this.handleKeyDown = this.handleKeyDown.bind (this) ' – boxtrain

+0

không phải lúc nào cũng vậy. chỉ liên kết nó với chính nó nếu thành phần đó cũng nên xử lý các sự kiện đó. cho giao diện người dùng phức tạp (như các ứng dụng web), tôi sử dụng các lớp 'InputHandler' xử lý và định tuyến tất cả các sự kiện của người dùng trên tất cả các thành phần. Nó đẹp hơn khi có mỗi/tất cả các thành phần có chức năng xử lý riêng của chúng, vì nếu có nhiều trình lắng nghe keydown được thêm vào cửa sổ, tất cả các thành phần 'handleKeydowns' sẽ cố gắng xử lý sự kiện so với 1' InputHandler' xử lý tất cả các sự kiện. cũng có trường hợp không có gì được thực hiện với 'this' trong hàm xử lý - trong trường hợp đó bạn cũng không cần phải ràng buộc. – Benny

Các vấn đề liên quan