Ich habe Probleme, Menüelemente mit einem Ereignishandler zu verbinden. Hier ist ein Mock der Benutzeroberfläche, der Statusänderungen im Laufe der Zeit zeigt. Es ist ein Dropdown-Menü (über Bootstrap), wobei der Hauptmenüpunkt die aktuelle Auswahl anzeigt:
[ANN]<click ... [ANN] ... [BOB]<click ... [BOB]
[Ann] [Ann]
[Bob]<click + ajax [Bob]
[Cal] [Cal]
Das Endziel besteht darin, den Seiteninhalt asynchron basierend auf der Auswahl des Benutzers zu ändern. Ein Klick auf Bob sollte die handleClick
auslösen, ist es aber nicht.
Als Randbemerkung bin ich mit der Art und Weise, wie ComponentDidMount this.handleClick();
aufruft, nicht besonders glücklich, aber es funktioniert vorerst als eine Möglichkeit, erste Menüinhalte vom Server abzurufen.
/** @jsx React.DOM */
var CurrentSelection = React.createClass({
componentDidMount: function() {
this.handleClick();
},
handleClick: function(event) {
alert('clicked');
// Ajax details ommitted since we never get here via onClick
},
getInitialState: function() {
return {title: "Loading items...", items: []};
},
render: function() {
var itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
});
return <ul className='nav'>
<li className='dropdown'>
<a href='#' className='dropdown-toggle' data-toggle='dropdown'>{this.state.title}</a>
<ul className='dropdown-menu'>{itemNodes}</ul>
</li>
</ul>;
}
});
$(document).ready(function() {
React.renderComponent(
CurrentSelection(),
document.getElementById('item-selection')
);
});
Ich bin fast sicher, dass mein dunstiges Verständnis von Javascript-Scoping Schuld ist, aber alles, was ich bisher ausprobiert habe, ist fehlgeschlagen (einschließlich des Versuches, den Handler durch Requisiten zu übergeben).
Das Problem ist, dass Sie die Elementknoten mit einer anonymen Funktion erstellen und this
die window
bedeutet. Das Update besteht darin, .bind(this)
zur anonymen Funktion hinzuzufügen.
var itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
}.bind(this));
Oder erstellen Sie eine Kopie von this
und verwenden Sie stattdessen Folgendes:
var _this = this, itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={_this.handleClick}>{item}</a></li>;
})
Da ich die Spezifikation der Aufgabe für "Anna", "Bob", "Cal" verstehen kann, kann die Lösung die folgende sein (basierend auf einer Reaktionskomponente und ES6):
import React, { Component } from "react"
export default class CurrentSelection extends Component {
constructor() {
super()
this.state = {
index: 0
}
this.list = ["Anna", "Bob", "Cal"]
}
listLi = list => {
return list.map((item, index) => (
<li key={index}>
<a
name={item}
href="#"
onClick={e => this.onEvent(e, index)}
>
{item}
</a>
</li>
))
}
onEvent = (e, index) => {
console.info("CurrentSelection->onEvent()", { [e.target.name]: index })
this.setState({ index })
}
getCurrentSelection = () => {
const { index } = this.state
return this.list[index]
}
render() {
return (
<div>
<ul>{this.listLi(this.list)}</ul>
<div>{this.getCurrentSelection()}</div>
</div>
)
}
}