我在从React中的表行调用click事件时遇到麻烦。下面是我的代码。我有一个单独的函数来单独填充行,但似乎我弄乱了绑定信息。
import React, {Component, PropTypes} from 'react'; import Header from './Header'; export default class SongData extends Component { constructor(props, context) { super(props, context); } isEmpty(obj) { return Object.keys(obj).length === 0; } fetchDetails(song) { console.log(song); } renderResultRows(data) { var self = this; return data.map(function(song) { return ( <tr onClick={self.fetchDetails(song)}> <td data-title="Song">{song.S_SONG}</td> <td data-title="Movie">{song.S_MOVIE}</td> <td data-title="Year">{song.S_YEAR}</td> </tr> ); }.bind(this)); } render() { return ( <div id="no-more-tables"> <table className="table table-hover table-bordered table-striped"> <thead> <tr> <th>Song</th> <th>Movie</th> <th>Year</th> </tr> </thead> <tbody> {!this.isEmpty(this.props.searchResult) ? this.renderResultRows(this.props.searchResult) : ''} </tbody> </table> </div> ); }
}
首先,您要传递一个评估函数调用到您的onClick属性。
onClick
单独查看以下代码:
function foo(name) { return 'hello ' + name; } foo('bob');
您期望的输出为foo('bob')“ hello bob”。
foo('bob')
如果我将其传递给onClickprop,则完全相同。例如:
<button onClick={foo('bob')}
在这种情况下,我只是将字符串传递给onClick按钮的prop。的onClick(和其他事件的道具)希望被提供的功能(或ref)。我将进一步举例说明。
其次我看你有正确的意向试图维持使用的组合为你的函数正确的范围const self = this和bind。使用ES6 / 2015中的匿名函数可以更轻松地做到这一点,该函数始终保持声明它们的范围。
const self = this
bind
然后,我可以将您的代码更新为以下内容:
renderResultRows(data) { return data.map((song) => { // anon func maintains scope! // Pass in a function to our onClick, and make it anon // to maintain scope. The function body can be anything // which will be executed on click only. Our song value // is maintained via a closure so it works. return ( <tr onClick={() => this.fetchDetails(song)}> <td data-title="Song">{song.S_SONG}</td> <td data-title="Movie">{song.S_MOVIE}</td> <td data-title="Year">{song.S_YEAR}</td> </tr> ); }); // no need to bind with anon function }
但这仍然不是最佳的。当使用这样的匿名语法(例如<foo onClick={() => { console.log('clicked') })时,我们将在每个渲染器上创建一个新函数。如果您使用的是纯组件(例如,仅在提供新的prop实例时才应重新渲染的组件- 此检查是通过浅比较执行的),这可能是一个问题。始终尝试尽早创建函数,例如在构造函数中或通过类属性(如果您使用babel stage 1)来创建函数,这样始终传递相同的引用。
<foo onClick={() => { console.log('clicked') }
但是,对于您的示例,您需要将一个值“传递给”每个onClick处理程序。为此,您可以使用以下方法:
fetchSongDetails = () => { const song = e.target.getAttribute('data-item'); console.log('We need to get the details for ', song); } renderResultRows(data) { return data.map((song, index) => { // anon func maintains scope! // Pass in a function to our onClick, and make it anon // to maintain scope. The function body can be anything // which will be executed on click only. Our song value // is maintained via a closure so it works. return ( <tr key={index} data-item={song} onClick={this.fetchSongDetails}> <td data-title="Song">{song.S_SONG}</td> <td data-title="Movie">{song.S_MOVIE}</td> <td data-title="Year">{song.S_YEAR}</td> </tr> ); }); // no need to bind with anon function }
这是一个更好的方法。另请注意,我向key生成的每一行添加了一个prop。这是React的另一种最佳实践,因为react会在差异算法中使用唯一的密钥标识符。
key
我强烈建议您阅读以下内容: