In einfachem altem Javascript habe ich den DIV
<div class="movie" id="my_movie">
und den folgenden Javascript-Code
var myMovie = document.getElementById('my_movie');
myMovie.addEventListener('nv-enter', function (event) {
console.log('change scope');
});
Jetzt habe ich eine React-Komponente in dieser Komponente, in der Render-Methode gebe ich mein div zurück. Wie kann ich einen Ereignis-Listener für mein benutzerdefiniertes Ereignis hinzufügen? (Ich benutze diese Bibliothek für TV-Apps - Navigation )
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;
Update Nr. 1:
Ich habe alle in den Antworten enthaltenen Ideen angewendet. Ich habe die Navigationsbibliothek auf den Debug-Modus eingestellt und kann auf meinen Menüelementen nur über die Tastatur navigieren (wie Sie im Screenshot sehen können, konnte ich zu Filmen 4 navigieren), aber wenn ich ein Element im Menü oder fokussiere Drücken Sie die Eingabetaste. Ich sehe nichts in der Konsole.
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;
Ich habe einige Zeilen kommentiert, da ich in beiden Fällen nicht in der Lage bin, die zu protokollierenden Konsolenzeilen abzurufen.
Update Nr. 2: Diese Navigationsbibliothek funktioniert nicht gut mit React mit den ursprünglichen HTML-Tags. Daher musste ich die Optionen festlegen und die Tags umbenennen, um aria- * zu verwenden, damit React nicht beeinträchtigt wird.
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)
) vorbinden als auch ES7-Eigenschaftsinitialisierer mit Pfeilfunktionen ( ) verwenden, da FettpfeilfunktionenhandleNVEnter = enter => {}
immer gebunden sind. Wenn Sie die ES7-Syntax verwenden können, gehen Sie einfach damit um.aria-*
,data-*
da ARIA-Attribute aus einem Standardsatz stammen und Sie keine eigenen erstellen können. Datenattribute können beliebiger eingestellt werden.Antworten:
Wenn Sie DOM-Ereignisse verarbeiten müssen, die nicht bereits von React bereitgestellt wurden , müssen Sie nach dem Mounten der Komponente DOM-Listener hinzufügen:
Update: Zwischen Reaktion 13, 14 und 15 wurden Änderungen an der API vorgenommen, die sich auf meine Antwort auswirken. Im Folgenden finden Sie die neueste Methode zur Verwendung von React 15 und ES7. Siehe Antwortverlauf für ältere Versionen.
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> ); } }
Beispiel auf Codepen.io
quelle
findDOMNode
. In deinem Fallvar elem = this.refs.nv;
ist genug.edited Aug 19 at 6:19
Text unter dem Beitrag, um zum Revisionsverlauf zu gelangen .nv.dispatchEvent()
.Sie können die Methoden componentDidMount und componentWillUnmount verwenden:
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;
quelle
Zunächst einmal spielen benutzerdefinierte Ereignisse mit nativen React-Komponenten nicht gut. Sie können also nicht einfach
<div onMyCustomEvent={something}>
in der Renderfunktion sagen und müssen über das Problem nachdenken.Zweitens wird das Ereignis ausgelöst, nachdem Sie einen Blick auf die Dokumentation der von Ihnen verwendeten Bibliothek geworfen haben.
document.body
Selbst wenn es funktioniert hätte, würde Ihr Ereignishandler niemals ausgelöst.Stattdessen können Sie
componentDidMount
irgendwo in Ihrer Anwendung nv-enter durch Hinzufügen anhörendocument.body.addEventListener('nv-enter', function (event) { // logic });
Drücken Sie dann in der Rückruffunktion eine Funktion, die den Status der Komponente oder was auch immer Sie tun möchten, ändert.
quelle