Dalam javascript lama biasa saya memiliki DIV
<div class="movie" id="my_movie">
dan kode javascript berikut
var myMovie = document.getElementById('my_movie');
myMovie.addEventListener('nv-enter', function (event) {
console.log('change scope');
});
Sekarang saya memiliki Komponen React, di dalam komponen ini, dalam metode render, saya mengembalikan div saya. Bagaimana cara menambahkan event listener untuk acara khusus saya? (Saya menggunakan perpustakaan ini untuk aplikasi TV - navigasi )
import React, { Component } from 'react';
class MovieItem extends Component {
render() {
if(this.props.index === 0) {
return (
<div aria-nv-el aria-nv-el-current className="menu_item nv-default">
<div className="indicator selected"></div>
<div className="category">
<span className="title">{this.props.movieItem.caption.toUpperCase()}</span>
</div>
</div>
);
}
else {
return (
<div aria-nv-el className="menu_item nv-default">
<div className="indicator selected"></div>
<div className="category">
<span className="title">{this.props.movieItem.caption.toUpperCase()}</span>
</div>
</div>
);
}
}
}
export default MovieItem;
Perbarui # 1:
Saya menerapkan semua ide yang diberikan dalam jawaban. Saya mengatur perpustakaan navigasi ke mode debug dan saya dapat menavigasi item menu saya hanya berdasarkan keyboard (seperti yang Anda lihat di tangkapan layar, saya dapat menavigasi ke Film 4) tetapi ketika saya memfokuskan item di menu atau tekan enter, saya tidak melihat apa pun di konsol.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class MenuItem extends Component {
constructor(props) {
super(props);
// Pre-bind your event handler, or define it as a fat arrow in ES7/TS
this.handleNVFocus = this.handleNVFocus.bind(this);
this.handleNVEnter = this.handleNVEnter.bind(this);
this.handleNVRight = this.handleNVRight.bind(this);
}
handleNVFocus = event => {
console.log('Focused: ' + this.props.menuItem.caption.toUpperCase());
}
handleNVEnter = event => {
console.log('Enter: ' + this.props.menuItem.caption.toUpperCase());
}
handleNVRight = event => {
console.log('Right: ' + this.props.menuItem.caption.toUpperCase());
}
componentDidMount() {
ReactDOM.findDOMNode(this).addEventListener('nv-focus', this.handleNVFocus);
ReactDOM.findDOMNode(this).addEventListener('nv-enter', this.handleNVEnter);
ReactDOM.findDOMNode(this).addEventListener('nv-right', this.handleNVEnter);
//this.refs.nv.addEventListener('nv-focus', this.handleNVFocus);
//this.refs.nv.addEventListener('nv-enter', this.handleNVEnter);
//this.refs.nv.addEventListener('nv-right', this.handleNVEnter);
}
componentWillUnmount() {
ReactDOM.findDOMNode(this).removeEventListener('nv-focus', this.handleNVFocus);
ReactDOM.findDOMNode(this).removeEventListener('nv-enter', this.handleNVEnter);
ReactDOM.findDOMNode(this).removeEventListener('nv-right', this.handleNVRight);
//this.refs.nv.removeEventListener('nv-focus', this.handleNVFocus);
//this.refs.nv.removeEventListener('nv-enter', this.handleNVEnter);
//this.refs.nv.removeEventListener('nv-right', this.handleNVEnter);
}
render() {
var attrs = this.props.index === 0 ? {"aria-nv-el-current": true} : {};
return (
<div ref="nv" aria-nv-el {...attrs} className="menu_item nv-default">
<div className="indicator selected"></div>
<div className="category">
<span className="title">{this.props.menuItem.caption.toUpperCase()}</span>
</div>
</div>
)
}
}
export default MenuItem;
Saya meninggalkan beberapa baris komentar karena dalam kedua kasus tersebut saya tidak bisa mendapatkan baris konsol untuk dicatat.
Pembaruan # 2: Pustaka navigasi ini tidak bekerja dengan baik dengan React dengan Tag Html aslinya, jadi saya harus mengatur opsi dan mengganti nama tag untuk menggunakan aria- * sehingga tidak akan mempengaruhi React.
navigation.setOption('prefix','aria-nv-el');
navigation.setOption('attrScope','aria-nv-scope');
navigation.setOption('attrScopeFOV','aria-nv-scope-fov');
navigation.setOption('attrScopeCurrent','aria-nv-scope-current');
navigation.setOption('attrElement','aria-nv-el');
navigation.setOption('attrElementFOV','aria-nv-el-fov');
navigation.setOption('attrElementCurrent','aria-nv-el-current');
this.handleNVEnter = this.handleNVEnter.bind(this)
) dan menggunakan penginisialisasi properti ES7 dengan fungsi panah (handleNVEnter = enter => {}
) karena fungsi panah lemak selalu terikat. Jika Anda dapat menggunakan sintaks ES7, lakukan saja.aria-*
kedata-*
karena atribut ARIA berasal dari kumpulan standar, Anda tidak dapat membuatnya sendiri. Atribut data dapat diatur secara lebih sewenang-wenang ke apa pun yang Anda inginkan.Jawaban:
Jika Anda perlu menangani kejadian DOM yang belum disediakan oleh React, Anda harus menambahkan pendengar DOM setelah komponen dipasang:
Pembaruan: Antara React 13, 14, dan 15 perubahan dibuat pada API yang mempengaruhi jawaban saya. Di bawah ini adalah cara terbaru menggunakan React 15 dan ES7. Lihat riwayat jawaban untuk versi yang lebih lama.
class MovieItem extends React.Component { componentDidMount() { // When the component is mounted, add your DOM listener to the "nv" elem. // (The "nv" elem is assigned in the render function.) this.nv.addEventListener("nv-enter", this.handleNvEnter); } componentWillUnmount() { // Make sure to remove the DOM listener when the component is unmounted. this.nv.removeEventListener("nv-enter", this.handleNvEnter); } // Use a class arrow function (ES7) for the handler. In ES6 you could bind() // a handler in the constructor. handleNvEnter = (event) => { console.log("Nv Enter:", event); } render() { // Here we render a single <div> and toggle the "aria-nv-el-current" attribute // using the attribute spread operator. This way only a single <div> // is ever mounted and we don't have to worry about adding/removing // a DOM listener every time the current index changes. The attrs // are "spread" onto the <div> in the render function: {...attrs} const attrs = this.props.index === 0 ? {"aria-nv-el-current": true} : {}; // Finally, render the div using a "ref" callback which assigns the mounted // elem to a class property "nv" used to add the DOM listener to. return ( <div ref={elem => this.nv = elem} aria-nv-el {...attrs} className="menu_item nv-default"> ... </div> ); } }
Contoh di Codepen.io
sumber
findDOMNode
. Dalam kasus Andavar elem = this.refs.nv;
sudah cukup.edited Aug 19 at 6:19
teks di bawah posting, yang membawa Anda ke riwayat revisi .nv.dispatchEvent()
jika perlu.Anda bisa menggunakan componentDidMount dan componentWillUnmount metode:
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class MovieItem extends Component { _handleNVEvent = event => { ... }; componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('nv-event', this._handleNVEvent); } componentWillUnmount() { ReactDOM.findDOMNode(this).removeEventListener('nv-event', this._handleNVEvent); } [...] } export default MovieItem;
sumber
Pertama, acara khusus tidak berfungsi dengan baik dengan komponen React secara native. Jadi Anda tidak bisa hanya mengatakan
<div onMyCustomEvent={something}>
dalam fungsi render, dan harus memikirkan masalahnya.Kedua, setelah mengintip dokumentasi untuk pustaka yang Anda gunakan, peristiwa sebenarnya diaktifkan
document.body
, jadi meskipun berhasil, penangan peristiwa Anda tidak akan pernah terpicu.Sebagai gantinya, di dalam
componentDidMount
suatu tempat di aplikasi Anda, Anda dapat mendengarkan nv-enter dengan menambahkandocument.body.addEventListener('nv-enter', function (event) { // logic });
Kemudian, di dalam fungsi callback, tekan fungsi yang mengubah status komponen, atau apa pun yang ingin Anda lakukan.
sumber